1e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb/* 2e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb * Copyright 2015 Google Inc. 3e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb * 4e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb * Use of this source code is governed by a BSD-style license that can be 5e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb * found in the LICENSE file. 6e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb */ 7e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 8e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#ifndef SkFindAndPositionGlyph_DEFINED 9e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#define SkFindAndPositionGlyph_DEFINED 10e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 11e59124ed1a62f1fec79679c38cabed622a756f75herb#include "SkAutoKern.h" 12e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkGlyph.h" 13e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkGlyphCache.h" 14e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkPaint.h" 15e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkTemplates.h" 164c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb#include "SkUtils.h" 17221524de3be1fc343ad328c5e99562f32b5cad9cbungeman#include <utility> 18e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 19e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb// Calculate a type with the same size as the max of all the Ts. 20e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb// This must be top level because the is no specialization of inner classes. 21e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbtemplate<typename... Ts> struct SkMaxSizeOf; 22e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 23e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbtemplate<> 24e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbstruct SkMaxSizeOf<> { 25e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static const size_t value = 0; 26e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb}; 27e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 28e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbtemplate<typename H, typename... Ts> 29e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbstruct SkMaxSizeOf<H, Ts...> { 30e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static const size_t value = 31e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb sizeof(H) >= SkMaxSizeOf<Ts...>::value ? sizeof(H) : SkMaxSizeOf<Ts...>::value; 32e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb}; 33e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 34d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 35d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// This is a temporary helper function to work around a bug in the code generation 36d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// for aarch64 (arm) on GCC 4.9. This bug does not show up on other platforms, so it 37d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// seems to be an aarch64 backend problem. 38d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// 39d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// GCC 4.9 on ARM64 does not generate the proper constructor code for PositionReader or 40d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// GlyphFindAndPlace. The vtable is not set properly without adding the fixme code. 41d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// The implementation is in SkDraw.cpp. 42d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbextern void FixGCC49Arm64Bug(int v); 43d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 44e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbclass SkFindAndPlaceGlyph { 45e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbpublic: 46e59124ed1a62f1fec79679c38cabed622a756f75herb template<typename ProcessOneGlyph> 474c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb static void ProcessText( 484c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::TextEncoding, const char text[], size_t byteLength, 494c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment, 504c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph); 51e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // ProcessPosText handles all cases for finding and positioning glyphs. It has a very large 52e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // multiplicity. It figures out the glyph, position and rounding and pass those parameters to 53e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // processOneGlyph. 54e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // 55e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // The routine processOneGlyph passed in by the client has the following signature: 56e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // void f(const SkGlyph& glyph, SkPoint position, SkPoint rounding); 57e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // 58e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Sub-pixel positioning (2) - use sub-pixel positioning. 59e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Text alignment (3) - text alignment with respect to the glyph's width. 60e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Matrix type (3) - special cases for translation and X-coordinate scaling. 61e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Components per position (2) - the positions vector can have a common Y with different 62e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Xs, or XY-pairs. 63e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Axis Alignment (for sub-pixel positioning) (3) - when using sub-pixel positioning, round 64e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // to a whole coordinate instead of using sub-pixel positioning. 65e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // The number of variations is 108 for sub-pixel and 36 for full-pixel. 66e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // This routine handles all of them using inline polymorphic variable (no heap allocation). 67e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename ProcessOneGlyph> 684c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb static void ProcessPosText( 694c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::TextEncoding, const char text[], size_t byteLength, 704c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPerPosition, 714c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::Align textAlignment, 724c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph); 73e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 74e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbprivate: 75e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // UntaggedVariant is a pile of memory that can hold one of the Ts. It provides a way 76e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // to initialize that memory in a typesafe way. 77e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename... Ts> 78e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class UntaggedVariant { 79e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 80e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb UntaggedVariant() { } 81e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 82e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb ~UntaggedVariant() { } 83e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb UntaggedVariant(const UntaggedVariant&) = delete; 84e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb UntaggedVariant& operator=(const UntaggedVariant&) = delete; 85e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb UntaggedVariant(UntaggedVariant&&) = delete; 86e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb UntaggedVariant& operator=(UntaggedVariant&&) = delete; 87e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 88e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename Variant, typename... Args> 89e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb void initialize(Args&&... args) { 90e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkASSERT(sizeof(Variant) <= sizeof(fSpace)); 91e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb #if defined(_MSC_VER) && _MSC_VER < 1900 92e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb #define alignof __alignof 93e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb #endif 94e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkASSERT(alignof(Variant) <= alignof(Space)); 95221524de3be1fc343ad328c5e99562f32b5cad9cbungeman new(&fSpace) Variant(std::forward<Args>(args)...); 96e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 97e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 98e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 99e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb typedef SkAlignedSStorage<SkMaxSizeOf<Ts...>::value> Space; 100e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb Space fSpace; 101e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 102e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 103e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // PolymorphicVariant holds subclasses of Base without slicing. Ts must be subclasses of Base. 104e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename Base, typename... Ts> 105e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class PolymorphicVariant { 106e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 107e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb typedef UntaggedVariant<Ts...> Variants; 108e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 109e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename Initializer> 110e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb PolymorphicVariant(Initializer&& initializer) { 111e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb initializer(&fVariants); 112e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 113e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb ~PolymorphicVariant() { get()->~Base(); } 114e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb Base* get() const { return reinterpret_cast<Base*>(&fVariants); } 115e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb Base* operator->() const { return get(); } 116e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb Base& operator*() const { return *get(); } 117e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 118e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 119e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb mutable Variants fVariants; 120e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 121e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 1224c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb // GlyphFinderInterface is the polymorphic base for classes that parse a stream of chars into 1234c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb // the right UniChar (or GlyphID) and lookup up the glyph on the cache. The concrete 1244c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb // implementations are: Utf8GlyphFinder, Utf16GlyphFinder, Utf32GlyphFinder, 1254c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb // and GlyphIdGlyphFinder. 1264c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class GlyphFinderInterface { 1274c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1284c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb virtual ~GlyphFinderInterface() {} 1294c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb virtual const SkGlyph& lookupGlyph(const char** text) = 0; 1304c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb virtual const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) = 0; 1314c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 1324c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1334c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class UtfNGlyphFinder : public GlyphFinderInterface { 1344c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1354c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb UtfNGlyphFinder(SkGlyphCache* cache) : fCache(cache) { SkASSERT(cache != nullptr); } 1364c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1374c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& lookupGlyph(const char** text) override { 1384c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkASSERT(text != nullptr); 1394c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return fCache->getUnicharMetrics(nextUnichar(text)); 1404c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1414c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override { 1424c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkASSERT(text != nullptr); 1434c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return fCache->getUnicharMetrics(nextUnichar(text), x, y); 1444c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1454c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1464c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb private: 1474c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb virtual SkUnichar nextUnichar(const char** text) = 0; 1484c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* fCache; 1494c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 1504c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1514c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class Utf8GlyphFinder final : public UtfNGlyphFinder { 1524c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1534c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf8GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { } 1544c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1554c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb private: 1564c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkUnichar nextUnichar(const char** text) override { return SkUTF8_NextUnichar(text); } 1574c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 1584c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1594c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class Utf16GlyphFinder final : public UtfNGlyphFinder { 1604c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1614c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf16GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { } 1624c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1634c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb private: 1644c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkUnichar nextUnichar(const char** text) override { 1654c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return SkUTF16_NextUnichar((const uint16_t**)text); 1664c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1674c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 1684c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1694c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class Utf32GlyphFinder final : public UtfNGlyphFinder { 1704c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1714c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf32GlyphFinder(SkGlyphCache* cache) : UtfNGlyphFinder(cache) { } 1724c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1734c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb private: 1744c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkUnichar nextUnichar(const char** text) override { 1754c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const int32_t* ptr = *(const int32_t**)text; 1764c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkUnichar uni = *ptr++; 1774c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb *text = (const char*)ptr; 1784c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return uni; 1794c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1804c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 1814c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1824c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class GlyphIdGlyphFinder final : public GlyphFinderInterface { 1834c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 1844c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb GlyphIdGlyphFinder(SkGlyphCache* cache) : fCache(cache) { SkASSERT(cache != nullptr); } 1854c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1864c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& lookupGlyph(const char** text) override { 1874c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return fCache->getGlyphIDMetrics(nextGlyphId(text)); 1884c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1894c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& lookupGlyphXY(const char** text, SkFixed x, SkFixed y) override { 1904c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return fCache->getGlyphIDMetrics(nextGlyphId(text), x, y); 1914c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 1924c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1934c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb private: 1944c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb uint16_t nextGlyphId(const char** text) { 1954c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkASSERT(text != nullptr); 1964c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 1974c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const uint16_t* ptr = *(const uint16_t**)text; 1984c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb uint16_t glyphID = *ptr; 1994c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ptr += 1; 2004c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb *text = (const char*)ptr; 2014c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb return glyphID; 2024c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 2034c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* fCache; 2044c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 2054c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 2064c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb typedef PolymorphicVariant< 2074c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb GlyphFinderInterface, 2084c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf8GlyphFinder, 2094c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf16GlyphFinder, 2104c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Utf32GlyphFinder, 2114c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb GlyphIdGlyphFinder> LookupGlyphVariant; 2124c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 2134c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb class LookupGlyph : public LookupGlyphVariant { 2144c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb public: 2154c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph(SkPaint::TextEncoding encoding, SkGlyphCache* cache) 2164c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb : LookupGlyphVariant( 2174c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb [&](LookupGlyphVariant::Variants* to_init) { 2184c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb switch(encoding) { 2194c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb case SkPaint::kUTF8_TextEncoding: 2204c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init->initialize<Utf8GlyphFinder>(cache); 2214c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb break; 2224c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb case SkPaint::kUTF16_TextEncoding: 2234c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init->initialize<Utf16GlyphFinder>(cache); 2244c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb break; 2254c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb case SkPaint::kUTF32_TextEncoding: 2264c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init->initialize<Utf32GlyphFinder>(cache); 2274c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb break; 2284c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb case SkPaint::kGlyphID_TextEncoding: 2294c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init->initialize<GlyphIdGlyphFinder>(cache); 2304c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb break; 2314c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 2324c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb } 2334c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ) { } 2344c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb }; 2354c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 236e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // PositionReaderInterface reads a point from the pos vector. 237e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * HorizontalPositions - assumes a common Y for many X values. 238e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * ArbitraryPositions - a list of (X,Y) pairs. 239e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class PositionReaderInterface { 240e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 241e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb virtual ~PositionReaderInterface() { } 242e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb virtual SkPoint nextPoint() = 0; 243d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // This is only here to fix a GCC 4.9 aarch64 code gen bug. 244d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // See comment at the top of the file. 245d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb virtual int forceUseForBug() = 0; 246e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 247e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 248e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class HorizontalPositions final : public PositionReaderInterface { 249e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 250e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb explicit HorizontalPositions(const SkScalar* positions) 251e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb : fPositions(positions) { } 252e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 253e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint nextPoint() override { 254e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkScalar x = *fPositions++; 255e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {x, 0}; 256e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 257e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 258d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int forceUseForBug() override { return 1; } 259d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 260e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 261e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkScalar* fPositions; 262e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 263e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 264e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class ArbitraryPositions final : public PositionReaderInterface { 265e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 266e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb explicit ArbitraryPositions(const SkScalar* positions) 267e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb : fPositions(positions) { } 268e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 269e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint nextPoint() override { 270e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint to_return{fPositions[0], fPositions[1]}; 271e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb fPositions += 2; 272e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return to_return; 273e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 274e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 275d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int forceUseForBug() override { return 2; } 276d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 277e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 278e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkScalar* fPositions; 279e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 280e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 281e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb typedef PolymorphicVariant<PositionReaderInterface, HorizontalPositions, ArbitraryPositions> 282e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb PositionReader; 283e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 284e59124ed1a62f1fec79679c38cabed622a756f75herb // MapperInterface given a point map it through the matrix. There are several shortcut 285e59124ed1a62f1fec79679c38cabed622a756f75herb // variants. 286e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * TranslationMapper - assumes a translation only matrix. 287e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * XScaleMapper - assumes an X scaling and a translation. 288e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * GeneralMapper - Does all other matricies. 289e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class MapperInterface { 290e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 291e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb virtual ~MapperInterface() { } 292e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 293e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb virtual SkPoint map(SkPoint position) const = 0; 294e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 295e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 296e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class TranslationMapper final : public MapperInterface { 297e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 298e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb TranslationMapper(const SkMatrix& matrix, const SkPoint origin) 299e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb : fTranslate(matrix.mapXY(origin.fX, origin.fY)) { } 300e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 301e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint map(SkPoint position) const override { 302e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return position + fTranslate; 303e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 304e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 305e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 306e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkPoint fTranslate; 307e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 308e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 309e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class XScaleMapper final : public MapperInterface { 310e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 311e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb XScaleMapper(const SkMatrix& matrix, const SkPoint origin) 312e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb : fTranslate(matrix.mapXY(origin.fX, origin.fY)), fXScale(matrix.getScaleX()) { } 313e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 314e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint map(SkPoint position) const override { 315e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {fXScale * position.fX + fTranslate.fX, fTranslate.fY}; 316e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 317e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 318e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 319e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkPoint fTranslate; 320e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkScalar fXScale; 321e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 322e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 323e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // The caller must keep matrix alive while this class is used. 324e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class GeneralMapper final : public MapperInterface { 325e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 326e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GeneralMapper(const SkMatrix& matrix, const SkPoint origin) 327e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb : fOrigin(origin), fMatrix(matrix), fMapProc(matrix.getMapXYProc()) { } 328e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 329e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint map(SkPoint position) const override { 330e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint result; 331e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb fMapProc(fMatrix, position.fX + fOrigin.fX, position.fY + fOrigin.fY, &result); 332e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return result; 333e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 334e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 335e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 336e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkPoint fOrigin; 337e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkMatrix& fMatrix; 338e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const SkMatrix::MapXYProc fMapProc; 339e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 340e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 341e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb typedef PolymorphicVariant< 342e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb MapperInterface, TranslationMapper, XScaleMapper, GeneralMapper> Mapper; 343e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 344e59124ed1a62f1fec79679c38cabed622a756f75herb // TextAlignmentAdjustment handles shifting the glyph based on its width. 345e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static SkPoint TextAlignmentAdjustment(SkPaint::Align textAlignment, const SkGlyph& glyph) { 346e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (textAlignment) { 347e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kLeft_Align: 348e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {0.0f, 0.0f}; 349e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kCenter_Align: 3506b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner return {SkFloatToScalar(glyph.fAdvanceX) / 2, 3516b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner SkFloatToScalar(glyph.fAdvanceY) / 2}; 352e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kRight_Align: 3536b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner return {SkFloatToScalar(glyph.fAdvanceX), 3546b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner SkFloatToScalar(glyph.fAdvanceY)}; 355e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 356e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Even though the entire enum is covered above, MVSC doesn't think so. Make it happy. 357e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkFAIL("Should never get here."); 358e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {0.0f, 0.0f}; 359e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 360e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 361e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // The "call" to SkFixedToScalar is actually a macro. It's macros all the way down. 362e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Needs to be a macro because you can't have a const float unless you make it constexpr. 363e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb #define kSubpixelRounding (SkFixedToScalar(SkGlyph::kSubpixelRound)) 364e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 365e59124ed1a62f1fec79679c38cabed622a756f75herb // The SubpixelPositionRounding function returns a point suitable for rounding a sub-pixel 366e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // positioned glyph. 367e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static SkPoint SubpixelPositionRounding(SkAxisAlignment axisAlignment) { 368e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (axisAlignment) { 369e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kX_SkAxisAlignment: 370fa5e5c75218a877d30177d08686d8ec0ea050b0abungeman return {kSubpixelRounding, SK_ScalarHalf}; 371e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kY_SkAxisAlignment: 372e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {SK_ScalarHalf, kSubpixelRounding}; 373e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kNone_SkAxisAlignment: 374e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {kSubpixelRounding, kSubpixelRounding}; 375e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 376e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkFAIL("Should not get here."); 377e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {0.0f, 0.0f}; 378e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 379e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 380e59124ed1a62f1fec79679c38cabed622a756f75herb // The SubpixelAlignment function produces a suitable position for the glyph cache to 381e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // produce the correct sub-pixel alignment. If a position is aligned with an axis a shortcut 382e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // of 0 is used for the sub-pixel position. 383e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static SkIPoint SubpixelAlignment(SkAxisAlignment axisAlignment, SkPoint position) { 384db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner // Only the fractional part of position.fX and position.fY matter, because the result of 385db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner // this function will just be passed to FixedToSub. 386e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (axisAlignment) { 387e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kX_SkAxisAlignment: 388db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner return {SkScalarToFixed(SkScalarFraction(position.fX) + kSubpixelRounding), 0}; 389e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kY_SkAxisAlignment: 390db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner return {0, SkScalarToFixed(SkScalarFraction(position.fY) + kSubpixelRounding)}; 391e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kNone_SkAxisAlignment: 392db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner return {SkScalarToFixed(SkScalarFraction(position.fX) + kSubpixelRounding), 393db6bd3239fd5e35797a9aa36eb0044ecbe5557c4benjaminwagner SkScalarToFixed(SkScalarFraction(position.fY) + kSubpixelRounding)}; 394e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 395e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkFAIL("Should not get here."); 396e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb return {0, 0}; 397e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 398e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 399e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb #undef kSubpixelRounding 400e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 401e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // GlyphFindAndPlaceInterface given the text and position finds the correct glyph and does 402e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // glyph specific position adjustment. The findAndPositionGlyph method takes text and 403e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // position and calls processOneGlyph with the correct glyph, final position and rounding 404e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // terms. The final position is not rounded yet and is the responsibility of processOneGlyph. 405e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename ProcessOneGlyph> 406e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class GlyphFindAndPlaceInterface : SkNoncopyable { 407e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 408fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein virtual ~GlyphFindAndPlaceInterface() { } 409e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 410e59124ed1a62f1fec79679c38cabed622a756f75herb // findAndPositionGlyph calculates the position of the glyph, finds the glyph, and 411e59124ed1a62f1fec79679c38cabed622a756f75herb // returns the position of where the next glyph will be using the glyph's advance and 412e59124ed1a62f1fec79679c38cabed622a756f75herb // possibly kerning. The returned position is used by drawText, but ignored by drawPosText. 413e59124ed1a62f1fec79679c38cabed622a756f75herb // The compiler should prune all this calculation if the return value is not used. 414e59124ed1a62f1fec79679c38cabed622a756f75herb // 415e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // This should be a pure virtual, but some versions of GCC <= 4.8 have a bug that causes a 416e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // compile error. 417e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // See GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60277 418e59124ed1a62f1fec79679c38cabed622a756f75herb virtual SkPoint findAndPositionGlyph( 419e59124ed1a62f1fec79679c38cabed622a756f75herb const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) { 420e59124ed1a62f1fec79679c38cabed622a756f75herb SkFAIL("Should never get here."); 421e59124ed1a62f1fec79679c38cabed622a756f75herb return {0.0f, 0.0f}; 422fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein } 423e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 424e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 425e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // GlyphFindAndPlaceSubpixel handles finding and placing glyphs when sub-pixel positioning is 426e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // requested. After it has found and placed the glyph it calls the templated function 427e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // ProcessOneGlyph in order to actually perform an action. 428e59124ed1a62f1fec79679c38cabed622a756f75herb template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, 429e59124ed1a62f1fec79679c38cabed622a756f75herb SkAxisAlignment kAxisAlignment> 430e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class GlyphFindAndPlaceSubpixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> { 431e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 4324c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb GlyphFindAndPlaceSubpixel(LookupGlyph& glyphFinder) 433d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb : fGlyphFinder(glyphFinder) { 434d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb FixGCC49Arm64Bug(1); 435d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 436e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 437e59124ed1a62f1fec79679c38cabed622a756f75herb SkPoint findAndPositionGlyph( 438e59124ed1a62f1fec79679c38cabed622a756f75herb const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override { 439428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby 440e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (kTextAlignment != SkPaint::kLeft_Align) { 441e59124ed1a62f1fec79679c38cabed622a756f75herb // Get the width of an un-sub-pixel positioned glyph for calculating the 442e59124ed1a62f1fec79679c38cabed622a756f75herb // alignment. This is not needed for kLeftAlign because its adjustment is 443e59124ed1a62f1fec79679c38cabed622a756f75herb // always {0, 0}. 444e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const char* tempText = *text; 4454c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph &metricGlyph = fGlyphFinder->lookupGlyph(&tempText); 446e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 447e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (metricGlyph.fWidth <= 0) { 448386127f1d431ef64bf655f39994f17daadfb5269herb // Exiting early, be sure to update text pointer. 449386127f1d431ef64bf655f39994f17daadfb5269herb *text = tempText; 450428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby return position + SkPoint{SkFloatToScalar(metricGlyph.fAdvanceX), 451428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby SkFloatToScalar(metricGlyph.fAdvanceY)}; 452e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 453e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 454e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Adjust the final position by the alignment adjustment. 455428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby position -= TextAlignmentAdjustment(kTextAlignment, metricGlyph); 456e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 457e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 458e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Find the glyph. 459428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby SkIPoint lookupPosition = SkScalarsAreFinite(position.fX, position.fY) 460428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby ? SubpixelAlignment(kAxisAlignment, position) 461428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby : SkIPoint{0, 0}; 462e59124ed1a62f1fec79679c38cabed622a756f75herb const SkGlyph& renderGlyph = 4634c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb fGlyphFinder->lookupGlyphXY(text, lookupPosition.fX, lookupPosition.fY); 464e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 465e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // If the glyph has no width (no pixels) then don't bother processing it. 466e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (renderGlyph.fWidth > 0) { 467428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby processOneGlyph(renderGlyph, position, 468e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SubpixelPositionRounding(kAxisAlignment)); 469e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 470428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby return position + SkPoint{SkFloatToScalar(renderGlyph.fAdvanceX), 471428dfe01fca286d6ef952242388a1075b80bb4eeHerb Derby SkFloatToScalar(renderGlyph.fAdvanceY)}; 472e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 473e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 474e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 4754c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph& fGlyphFinder; 476e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 477e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 478e59124ed1a62f1fec79679c38cabed622a756f75herb enum SelectKerning { 479e59124ed1a62f1fec79679c38cabed622a756f75herb kNoKerning = false, 480e59124ed1a62f1fec79679c38cabed622a756f75herb kUseKerning = true 481e59124ed1a62f1fec79679c38cabed622a756f75herb }; 482e59124ed1a62f1fec79679c38cabed622a756f75herb 483e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // GlyphFindAndPlaceFullPixel handles finding and placing glyphs when no sub-pixel 484e59124ed1a62f1fec79679c38cabed622a756f75herb // positioning is requested. The kUseKerning argument should be true for drawText, and false 485e59124ed1a62f1fec79679c38cabed622a756f75herb // for drawPosText. 486e59124ed1a62f1fec79679c38cabed622a756f75herb template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment, SelectKerning kUseKerning> 487e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb class GlyphFindAndPlaceFullPixel final : public GlyphFindAndPlaceInterface<ProcessOneGlyph> { 488e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb public: 4894c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb GlyphFindAndPlaceFullPixel(LookupGlyph& glyphFinder) 4904c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb : fGlyphFinder(glyphFinder) { 491d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb FixGCC49Arm64Bug(2); 492e59124ed1a62f1fec79679c38cabed622a756f75herb // Kerning can only be used with SkPaint::kLeft_Align 493e59124ed1a62f1fec79679c38cabed622a756f75herb static_assert(!kUseKerning || SkPaint::kLeft_Align == kTextAlignment, 494e59124ed1a62f1fec79679c38cabed622a756f75herb "Kerning can only be used with left aligned text."); 495e59124ed1a62f1fec79679c38cabed622a756f75herb } 496e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 497e59124ed1a62f1fec79679c38cabed622a756f75herb SkPoint findAndPositionGlyph( 498e59124ed1a62f1fec79679c38cabed622a756f75herb const char** text, SkPoint position, ProcessOneGlyph&& processOneGlyph) override { 499e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint finalPosition = position; 5004c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& glyph = fGlyphFinder->lookupGlyph(text); 501e59124ed1a62f1fec79679c38cabed622a756f75herb if (kUseKerning) { 5026b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner finalPosition += {fAutoKern.adjust(glyph), 0.0f}; 503e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 504e59124ed1a62f1fec79679c38cabed622a756f75herb if (glyph.fWidth > 0) { 505e59124ed1a62f1fec79679c38cabed622a756f75herb finalPosition -= TextAlignmentAdjustment(kTextAlignment, glyph); 506e59124ed1a62f1fec79679c38cabed622a756f75herb processOneGlyph(glyph, finalPosition, {SK_ScalarHalf, SK_ScalarHalf}); 507e59124ed1a62f1fec79679c38cabed622a756f75herb } 5086b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner return finalPosition + SkPoint{SkFloatToScalar(glyph.fAdvanceX), 5096b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner SkFloatToScalar(glyph.fAdvanceY)}; 510e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 511e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 512e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb private: 5134c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph& fGlyphFinder; 5144c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 515e59124ed1a62f1fec79679c38cabed622a756f75herb SkAutoKern fAutoKern; 516e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 517e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 518e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // GlyphFindAndPlace is a large variant that encapsulates the multiple types of finding and 519e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // placing a glyph. There are three factors that go into the different factors. 520e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Is sub-pixel positioned - a boolean that says whether to use sub-pixel positioning. 521e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Text alignment - indicates if the glyph should be placed to the right, centered or left 522e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // of a given position. 523e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // * Axis alignment - indicates if the glyphs final sub-pixel position should be rounded to a 524e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // whole pixel if the glyph is aligned with an axis. This is only used for sub-pixel 525e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // positioning and allows the baseline to look crisp. 526e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename ProcessOneGlyph> 527e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb using GlyphFindAndPlace = PolymorphicVariant< 528e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceInterface<ProcessOneGlyph>, 529e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Subpixel 530e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNone_SkAxisAlignment>, 531e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment >, 532e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align, kY_SkAxisAlignment >, 533e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNone_SkAxisAlignment>, 534e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kX_SkAxisAlignment >, 535e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align, kY_SkAxisAlignment >, 536e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kNone_SkAxisAlignment>, 537e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kX_SkAxisAlignment >, 538e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceSubpixel<ProcessOneGlyph, SkPaint::kRight_Align, kY_SkAxisAlignment >, 539e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // Full pixel 540e59124ed1a62f1fec79679c38cabed622a756f75herb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kLeft_Align, kNoKerning>, 541e59124ed1a62f1fec79679c38cabed622a756f75herb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kCenter_Align, kNoKerning>, 542e59124ed1a62f1fec79679c38cabed622a756f75herb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, SkPaint::kRight_Align, kNoKerning> 543e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb >; 544e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 545e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // InitSubpixel is a helper function for initializing all the variants of 546e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb // GlyphFindAndPlaceSubpixel. 547e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb template<typename ProcessOneGlyph, SkPaint::Align kTextAlignment> 548e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb static void InitSubpixel( 549e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init, 550e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkAxisAlignment axisAlignment, 5514c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph& glyphFinder) { 552e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (axisAlignment) { 553e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kX_SkAxisAlignment: 554e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize<GlyphFindAndPlaceSubpixel< 5554c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ProcessOneGlyph, kTextAlignment, kX_SkAxisAlignment>>(glyphFinder); 556e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 557e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kNone_SkAxisAlignment: 558e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize<GlyphFindAndPlaceSubpixel< 5594c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ProcessOneGlyph, kTextAlignment, kNone_SkAxisAlignment>>(glyphFinder); 560e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 561e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case kY_SkAxisAlignment: 562e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize<GlyphFindAndPlaceSubpixel< 5634c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ProcessOneGlyph, kTextAlignment, kY_SkAxisAlignment>>(glyphFinder); 564e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 565e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 566e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 567e59124ed1a62f1fec79679c38cabed622a756f75herb 5684c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb static SkPoint MeasureText(LookupGlyph& glyphFinder, const char text[], size_t byteLength) { 5696b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner SkScalar x = 0, y = 0; 570e59124ed1a62f1fec79679c38cabed622a756f75herb const char* stop = text + byteLength; 571e59124ed1a62f1fec79679c38cabed622a756f75herb 572e59124ed1a62f1fec79679c38cabed622a756f75herb SkAutoKern autokern; 573e59124ed1a62f1fec79679c38cabed622a756f75herb 574e59124ed1a62f1fec79679c38cabed622a756f75herb while (text < stop) { 575e59124ed1a62f1fec79679c38cabed622a756f75herb // don't need x, y here, since all subpixel variants will have the 576e59124ed1a62f1fec79679c38cabed622a756f75herb // same advance 5774c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb const SkGlyph& glyph = glyphFinder->lookupGlyph(&text); 578e59124ed1a62f1fec79679c38cabed622a756f75herb 5796b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner x += autokern.adjust(glyph) + SkFloatToScalar(glyph.fAdvanceX); 5806b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner y += SkFloatToScalar(glyph.fAdvanceY); 581e59124ed1a62f1fec79679c38cabed622a756f75herb } 582e59124ed1a62f1fec79679c38cabed622a756f75herb SkASSERT(text == stop); 5836b3eacb0dfaeb3374d410c8c041bd39cd066e1eabenjaminwagner return {x, y}; 584e59124ed1a62f1fec79679c38cabed622a756f75herb } 585e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb}; 586e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 587e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbtemplate<typename ProcessOneGlyph> 588e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherbinline void SkFindAndPlaceGlyph::ProcessPosText( 5894c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength, 5904c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPoint offset, const SkMatrix& matrix, const SkScalar pos[], int scalarsPerPosition, 5914c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::Align textAlignment, 5924c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { 593e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 59427876bc1156bcdd15cac7f0fe6228eb7806b8e96bungeman SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText(); 5959be5ff6f9871ef22740094e7c25dd67329a73d20herb uint32_t mtype = matrix.getType(); 5964c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph glyphFinder(textEncoding, cache); 5974c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 5989be5ff6f9871ef22740094e7c25dd67329a73d20herb // Specialized code for handling the most common case for blink. The while loop is totally 5999be5ff6f9871ef22740094e7c25dd67329a73d20herb // de-virtualized. 6009be5ff6f9871ef22740094e7c25dd67329a73d20herb if (scalarsPerPosition == 1 6019be5ff6f9871ef22740094e7c25dd67329a73d20herb && textAlignment == SkPaint::kLeft_Align 6029be5ff6f9871ef22740094e7c25dd67329a73d20herb && axisAlignment == kX_SkAxisAlignment 6039be5ff6f9871ef22740094e7c25dd67329a73d20herb && cache->isSubpixel() 6049be5ff6f9871ef22740094e7c25dd67329a73d20herb && mtype <= SkMatrix::kTranslate_Mask) { 6059be5ff6f9871ef22740094e7c25dd67329a73d20herb typedef GlyphFindAndPlaceSubpixel< 6069be5ff6f9871ef22740094e7c25dd67329a73d20herb ProcessOneGlyph, SkPaint::kLeft_Align, kX_SkAxisAlignment> Positioner; 6079be5ff6f9871ef22740094e7c25dd67329a73d20herb HorizontalPositions positions{pos}; 6089be5ff6f9871ef22740094e7c25dd67329a73d20herb TranslationMapper mapper{matrix, offset}; 6094c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb Positioner positioner(glyphFinder); 6109be5ff6f9871ef22740094e7c25dd67329a73d20herb const char* cursor = text; 6119be5ff6f9871ef22740094e7c25dd67329a73d20herb const char* stop = text + byteLength; 6129be5ff6f9871ef22740094e7c25dd67329a73d20herb while (cursor < stop) { 6139be5ff6f9871ef22740094e7c25dd67329a73d20herb SkPoint mappedPoint = mapper.TranslationMapper::map( 6149be5ff6f9871ef22740094e7c25dd67329a73d20herb positions.HorizontalPositions::nextPoint()); 6159be5ff6f9871ef22740094e7c25dd67329a73d20herb positioner.Positioner::findAndPositionGlyph( 616221524de3be1fc343ad328c5e99562f32b5cad9cbungeman &cursor, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph)); 6179be5ff6f9871ef22740094e7c25dd67329a73d20herb } 6189be5ff6f9871ef22740094e7c25dd67329a73d20herb return; 6199be5ff6f9871ef22740094e7c25dd67329a73d20herb } 6209be5ff6f9871ef22740094e7c25dd67329a73d20herb 621e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb PositionReader positionReader{ 622e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb [&](PositionReader::Variants* to_init) { 623e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (2 == scalarsPerPosition) { 624e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->initialize<ArbitraryPositions>(pos); 625e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } else { 626e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->initialize<HorizontalPositions>(pos); 627e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 628d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb positionReader->forceUseForBug(); 629e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 630e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 631e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 632e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb Mapper mapper{ 633e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb [&](Mapper::Variants* to_init) { 634e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask) 635e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb || scalarsPerPosition == 2) { 636e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->initialize<GeneralMapper>(matrix, offset); 637e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } else if (mtype & SkMatrix::kScale_Mask) { 638e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->initialize<XScaleMapper>(matrix, offset); 639e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } else { 640e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->initialize<TranslationMapper>(matrix, offset); 641e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 642e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 643e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 644e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 645d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb GlyphFindAndPlace<ProcessOneGlyph> findAndPosition { 646e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { 647e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb if (cache->isSubpixel()) { 648e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (textAlignment) { 649e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kLeft_Align: 650e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( 6514c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init, axisAlignment, glyphFinder); 652e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 653e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kCenter_Align: 654e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb InitSubpixel<ProcessOneGlyph, SkPaint::kCenter_Align>( 6554c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init, axisAlignment, glyphFinder); 656e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 657e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kRight_Align: 658e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb InitSubpixel<ProcessOneGlyph, SkPaint::kRight_Align>( 6594c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init, axisAlignment, glyphFinder); 660e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 661e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 662e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } else { 663e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb switch (textAlignment) { 664e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kLeft_Align: 665e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize< 666e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 6674c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::kLeft_Align, kNoKerning>>(glyphFinder); 668e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 669e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kCenter_Align: 670e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize< 671e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 6724c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::kCenter_Align, kNoKerning>>(glyphFinder); 673e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 674e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb case SkPaint::kRight_Align: 675e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb to_init->template initialize< 676e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb GlyphFindAndPlaceFullPixel<ProcessOneGlyph, 6774c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::kRight_Align, kNoKerning>>(glyphFinder); 678e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb break; 679e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 680e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 681e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 682e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb }; 683e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 684e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb const char* stop = text + byteLength; 685e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb while (text < stop) { 686e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb SkPoint mappedPoint = mapper->map(positionReader->nextPoint()); 687e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb findAndPosition->findAndPositionGlyph( 688221524de3be1fc343ad328c5e99562f32b5cad9cbungeman &text, mappedPoint, std::forward<ProcessOneGlyph>(processOneGlyph)); 689e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb } 690e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb} 691e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb 692e59124ed1a62f1fec79679c38cabed622a756f75herbtemplate<typename ProcessOneGlyph> 693e59124ed1a62f1fec79679c38cabed622a756f75herbinline void SkFindAndPlaceGlyph::ProcessText( 6944c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPaint::TextEncoding textEncoding, const char text[], size_t byteLength, 6954c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkPoint offset, const SkMatrix& matrix, SkPaint::Align textAlignment, 6964c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkGlyphCache* cache, ProcessOneGlyph&& processOneGlyph) { 697e59124ed1a62f1fec79679c38cabed622a756f75herb 698e59124ed1a62f1fec79679c38cabed622a756f75herb // transform the starting point 699e59124ed1a62f1fec79679c38cabed622a756f75herb matrix.mapPoints(&offset, 1); 700e59124ed1a62f1fec79679c38cabed622a756f75herb 7014c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb LookupGlyph glyphFinder(textEncoding, cache); 7024c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb 703e59124ed1a62f1fec79679c38cabed622a756f75herb // need to measure first 704e59124ed1a62f1fec79679c38cabed622a756f75herb if (textAlignment != SkPaint::kLeft_Align) { 7054c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb SkVector stop = MeasureText(glyphFinder, text, byteLength); 706e59124ed1a62f1fec79679c38cabed622a756f75herb 707e59124ed1a62f1fec79679c38cabed622a756f75herb if (textAlignment == SkPaint::kCenter_Align) { 708e59124ed1a62f1fec79679c38cabed622a756f75herb stop *= SK_ScalarHalf; 709e59124ed1a62f1fec79679c38cabed622a756f75herb } 710e59124ed1a62f1fec79679c38cabed622a756f75herb offset -= stop; 711e59124ed1a62f1fec79679c38cabed622a756f75herb } 712e59124ed1a62f1fec79679c38cabed622a756f75herb 713e59124ed1a62f1fec79679c38cabed622a756f75herb GlyphFindAndPlace<ProcessOneGlyph> findAndPosition{ 714e59124ed1a62f1fec79679c38cabed622a756f75herb [&](typename GlyphFindAndPlace<ProcessOneGlyph>::Variants* to_init) { 715e59124ed1a62f1fec79679c38cabed622a756f75herb if (cache->isSubpixel()) { 71627876bc1156bcdd15cac7f0fe6228eb7806b8e96bungeman SkAxisAlignment axisAlignment = 71727876bc1156bcdd15cac7f0fe6228eb7806b8e96bungeman cache->getScalerContext()->computeAxisAlignmentForHText(); 718e59124ed1a62f1fec79679c38cabed622a756f75herb InitSubpixel<ProcessOneGlyph, SkPaint::kLeft_Align>( 7194c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb to_init, axisAlignment, glyphFinder); 720e59124ed1a62f1fec79679c38cabed622a756f75herb } else { 721e59124ed1a62f1fec79679c38cabed622a756f75herb to_init->template initialize< 722e59124ed1a62f1fec79679c38cabed622a756f75herb GlyphFindAndPlaceFullPixel< 7234c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb ProcessOneGlyph, SkPaint::kLeft_Align, kUseKerning>>(glyphFinder); 724e59124ed1a62f1fec79679c38cabed622a756f75herb } 725e59124ed1a62f1fec79679c38cabed622a756f75herb } 726e59124ed1a62f1fec79679c38cabed622a756f75herb }; 727e59124ed1a62f1fec79679c38cabed622a756f75herb 728e59124ed1a62f1fec79679c38cabed622a756f75herb const char* stop = text + byteLength; 729e59124ed1a62f1fec79679c38cabed622a756f75herb SkPoint current = offset; 730e59124ed1a62f1fec79679c38cabed622a756f75herb while (text < stop) { 731e59124ed1a62f1fec79679c38cabed622a756f75herb current = 732e59124ed1a62f1fec79679c38cabed622a756f75herb findAndPosition->findAndPositionGlyph( 733221524de3be1fc343ad328c5e99562f32b5cad9cbungeman &text, current, std::forward<ProcessOneGlyph>(processOneGlyph)); 734e59124ed1a62f1fec79679c38cabed622a756f75herb 735e59124ed1a62f1fec79679c38cabed622a756f75herb } 736e59124ed1a62f1fec79679c38cabed622a756f75herb} 737e59124ed1a62f1fec79679c38cabed622a756f75herb 738e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#endif // SkFindAndPositionGlyph_DEFINED 739