Herb Derby | b2922f6 | 2018-01-26 16:47:54 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #include "SkRemoteGlyphCache.h" |
| 9 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 10 | #include <iterator> |
| 11 | #include <memory> |
Mike Klein | 79aea6a | 2018-06-11 10:45:26 -0400 | [diff] [blame] | 12 | #include <new> |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 13 | #include <string> |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 14 | #include <tuple> |
| 15 | |
| 16 | #include "SkDevice.h" |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 17 | #include "SkDraw.h" |
Herb Derby | 1a9971e | 2018-07-19 13:41:15 -0400 | [diff] [blame] | 18 | #include "SkGlyphRun.h" |
Mike Reed | 6be4715 | 2018-10-05 10:54:15 -0400 | [diff] [blame] | 19 | #include "SkGlyphCache.h" |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 20 | #include "SkRemoteGlyphCacheImpl.h" |
Herb Derby | dce19a7 | 2018-04-18 16:02:17 -0400 | [diff] [blame] | 21 | #include "SkStrikeCache.h" |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 22 | #include "SkTLazy.h" |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 23 | #include "SkTraceEvent.h" |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 24 | #include "SkTypeface_remote.h" |
| 25 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 26 | #if SK_SUPPORT_GPU |
| 27 | #include "GrDrawOpAtlas.h" |
Herb Derby | 26cbe51 | 2018-05-24 14:39:01 -0400 | [diff] [blame] | 28 | #include "text/GrTextContext.h" |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 29 | #endif |
| 30 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 31 | static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc, |
| 32 | SkFontID font_id, |
| 33 | SkAutoDescriptor* ad) { |
| 34 | ad->reset(source_desc->getLength()); |
| 35 | auto* desc = ad->getDesc(); |
| 36 | desc->init(); |
| 37 | |
| 38 | // Rec. |
| 39 | { |
| 40 | uint32_t size; |
| 41 | auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size); |
| 42 | SkScalerContextRec rec; |
| 43 | std::memcpy(&rec, ptr, size); |
| 44 | rec.fFontID = font_id; |
| 45 | desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec); |
| 46 | } |
| 47 | |
Mike Klein | 48fb8d8 | 2018-10-10 13:10:24 -0400 | [diff] [blame] | 48 | // Effects. |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 49 | { |
| 50 | uint32_t size; |
Mike Klein | 48fb8d8 | 2018-10-10 13:10:24 -0400 | [diff] [blame] | 51 | auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size); |
| 52 | if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); } |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | desc->computeChecksum(); |
| 56 | return desc; |
| 57 | } |
| 58 | |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 59 | enum DescriptorType : bool { kKey = false, kDevice = true }; |
| 60 | static const SkDescriptor* create_descriptor( |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 61 | DescriptorType type, const SkPaint& paint, const SkFont& font, const SkMatrix& m, |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 62 | const SkSurfaceProps& props, SkScalerContextFlags flags, |
| 63 | SkAutoDescriptor* ad, SkScalerContextEffects* effects) { |
| 64 | SkScalerContextRec deviceRec; |
| 65 | bool enableTypefaceFiltering = (type == kDevice); |
| 66 | SkScalerContext::MakeRecAndEffects( |
Herb Derby | c341500 | 2018-11-08 16:40:26 -0500 | [diff] [blame] | 67 | font, paint, props, flags, m, &deviceRec, effects, enableTypefaceFiltering); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 68 | return SkScalerContext::AutoDescriptorGivenRecAndEffects(deviceRec, *effects, ad); |
| 69 | } |
| 70 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 71 | // -- Serializer ---------------------------------------------------------------------------------- |
| 72 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 73 | size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); } |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 74 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 75 | class Serializer { |
| 76 | public: |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 77 | Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { } |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 78 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 79 | template <typename T, typename... Args> |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 80 | T* emplace(Args&&... args) { |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 81 | auto result = allocate(sizeof(T), alignof(T)); |
| 82 | return new (result) T{std::forward<Args>(args)...}; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 83 | } |
| 84 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 85 | template <typename T> |
| 86 | void write(const T& data) { |
| 87 | T* result = (T*)allocate(sizeof(T), alignof(T)); |
| 88 | memcpy(result, &data, sizeof(T)); |
| 89 | } |
| 90 | |
| 91 | template <typename T> |
| 92 | T* allocate() { |
| 93 | T* result = (T*)allocate(sizeof(T), alignof(T)); |
| 94 | return result; |
| 95 | } |
| 96 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 97 | void writeDescriptor(const SkDescriptor& desc) { |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 98 | write(desc.getLength()); |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 99 | auto result = allocate(desc.getLength(), alignof(SkDescriptor)); |
| 100 | memcpy(result, &desc, desc.getLength()); |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 101 | } |
| 102 | |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 103 | void* allocate(size_t size, size_t alignment) { |
| 104 | size_t aligned = pad(fBuffer->size(), alignment); |
| 105 | fBuffer->resize(aligned + size); |
| 106 | return &(*fBuffer)[aligned]; |
| 107 | } |
| 108 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 109 | private: |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 110 | std::vector<uint8_t>* fBuffer; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 111 | }; |
| 112 | |
| 113 | // -- Deserializer ------------------------------------------------------------------------------- |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 114 | // Note that the Deserializer is reading untrusted data, we need to guard against invalid data. |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 115 | class Deserializer { |
| 116 | public: |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 117 | Deserializer(const volatile char* memory, size_t memorySize) |
| 118 | : fMemory(memory), fMemorySize(memorySize) {} |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 119 | |
| 120 | template <typename T> |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 121 | bool read(T* val) { |
| 122 | auto* result = this->ensureAtLeast(sizeof(T), alignof(T)); |
| 123 | if (!result) return false; |
| 124 | |
| 125 | memcpy(val, const_cast<const char*>(result), sizeof(T)); |
| 126 | return true; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 127 | } |
| 128 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 129 | bool readDescriptor(SkAutoDescriptor* ad) { |
| 130 | uint32_t desc_length = 0u; |
| 131 | if (!read<uint32_t>(&desc_length)) return false; |
| 132 | |
| 133 | auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor)); |
| 134 | if (!result) return false; |
| 135 | |
| 136 | ad->reset(desc_length); |
| 137 | memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length); |
| 138 | return true; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 139 | } |
| 140 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 141 | const volatile void* read(size_t size, size_t alignment) { |
| 142 | return this->ensureAtLeast(size, alignment); |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 143 | } |
| 144 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 145 | private: |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 146 | const volatile char* ensureAtLeast(size_t size, size_t alignment) { |
| 147 | size_t padded = pad(fBytesRead, alignment); |
| 148 | |
| 149 | // Not enough data |
| 150 | if (padded + size > fMemorySize) return nullptr; |
| 151 | |
| 152 | auto* result = fMemory + padded; |
| 153 | fBytesRead = padded + size; |
| 154 | return result; |
| 155 | } |
| 156 | |
| 157 | // Note that we read each piece of memory only once to guard against TOCTOU violations. |
| 158 | const volatile char* fMemory; |
| 159 | size_t fMemorySize; |
| 160 | size_t fBytesRead = 0u; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 161 | }; |
| 162 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 163 | // Paths use a SkWriter32 which requires 4 byte alignment. |
| 164 | static const size_t kPathAlignment = 4u; |
| 165 | |
| 166 | bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache) { |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 167 | uint64_t pathSize = 0u; |
| 168 | if (!deserializer->read<uint64_t>(&pathSize)) return false; |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 169 | |
| 170 | if (pathSize == 0u) return true; |
| 171 | |
| 172 | auto* path = deserializer->read(pathSize, kPathAlignment); |
| 173 | if (!path) return false; |
| 174 | |
| 175 | return cache->initializePath(glyph, path, pathSize); |
| 176 | } |
| 177 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 178 | size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const { |
| 179 | return key->getChecksum(); |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 180 | } |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 181 | |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 182 | bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const { |
| 183 | return *lhs == *rhs; |
| 184 | } |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 185 | |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 186 | struct StrikeSpec { |
| 187 | StrikeSpec() {} |
| 188 | StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_) |
| 189 | : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {} |
| 190 | SkFontID typefaceID = 0u; |
| 191 | SkDiscardableHandleId discardableHandleId = 0u; |
| 192 | /* desc */ |
| 193 | /* n X (glyphs ids) */ |
| 194 | }; |
| 195 | |
Herb Derby | 30a9d26 | 2018-04-06 16:49:57 -0400 | [diff] [blame] | 196 | // -- TrackLayerDevice ----------------------------------------------------------------------------- |
Herb Derby | 447b198 | 2018-08-23 18:19:03 -0400 | [diff] [blame] | 197 | SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice( |
| 198 | const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server, |
| 199 | const SkTextBlobCacheDiffCanvas::Settings& settings) |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 200 | : SkNoPixelsDevice(bounds, props) |
| 201 | , fStrikeServer(server) |
| 202 | , fSettings(settings) |
| 203 | , fPainter{props, kUnknown_SkColorType, SkScalerContextFlags::kFakeGammaAndBoostContrast} { |
Herb Derby | 447b198 | 2018-08-23 18:19:03 -0400 | [diff] [blame] | 204 | SkASSERT(fStrikeServer); |
| 205 | } |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 206 | |
Herb Derby | 447b198 | 2018-08-23 18:19:03 -0400 | [diff] [blame] | 207 | SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice( |
| 208 | const CreateInfo& cinfo, const SkPaint*) { |
| 209 | const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry); |
| 210 | return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer, fSettings); |
| 211 | } |
| 212 | |
| 213 | void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList( |
| 214 | const SkGlyphRunList& glyphRunList) { |
| 215 | for (auto& glyphRun : glyphRunList) { |
Herb Derby | 95e1760 | 2018-12-06 17:11:43 -0500 | [diff] [blame] | 216 | this->processGlyphRun(glyphRunList.origin(), glyphRun, glyphRunList.paint()); |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 217 | } |
Herb Derby | 447b198 | 2018-08-23 18:19:03 -0400 | [diff] [blame] | 218 | } |
| 219 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 220 | // -- SkTextBlobCacheDiffCanvas ------------------------------------------------------------------- |
Khushal | 3e7548c | 2018-05-23 15:45:01 -0700 | [diff] [blame] | 221 | SkTextBlobCacheDiffCanvas::Settings::Settings() = default; |
Khushal | 3e7548c | 2018-05-23 15:45:01 -0700 | [diff] [blame] | 222 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 223 | SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height, |
| 224 | const SkMatrix& deviceMatrix, |
| 225 | const SkSurfaceProps& props, |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 226 | SkStrikeServer* strikeServer, |
| 227 | Settings settings) |
| 228 | : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props, |
| 229 | strikeServer, settings)} {} |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 230 | |
Herb Derby | 90c7d9b | 2018-09-07 17:00:36 -0400 | [diff] [blame] | 231 | SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas( |
| 232 | int width, int height, const SkSurfaceProps& props, |
| 233 | SkStrikeServer* strikeServer, Settings settings) |
| 234 | : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>( |
| 235 | SkIRect::MakeWH(width, height), props, strikeServer, settings)} {} |
| 236 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 237 | SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 238 | |
| 239 | SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy( |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 240 | const SaveLayerRec& rec) { |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 241 | return kFullLayer_SaveLayerStrategy; |
| 242 | } |
| 243 | |
Mike Reed | 148b7fd | 2018-12-18 17:38:18 -0500 | [diff] [blame] | 244 | bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) { |
| 245 | return false; |
| 246 | } |
| 247 | |
Khushal | a05a31a | 2018-06-08 13:00:40 -0700 | [diff] [blame] | 248 | void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, |
| 249 | const SkPaint& paint) { |
| 250 | SkCanvas::onDrawTextBlob(blob, x, y, paint); |
Khushal | e70c5fb | 2018-05-31 13:38:57 -0700 | [diff] [blame] | 251 | } |
| 252 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 253 | struct WireTypeface { |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 254 | WireTypeface() = default; |
| 255 | WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed) |
| 256 | : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {} |
| 257 | |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 258 | SkFontID typefaceID; |
| 259 | int glyphCount; |
| 260 | SkFontStyle style; |
| 261 | bool isFixed; |
| 262 | }; |
| 263 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 264 | // SkStrikeServer ----------------------------------------- |
Herb Derby | b2922f6 | 2018-01-26 16:47:54 -0500 | [diff] [blame] | 265 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 266 | SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager) |
| 267 | : fDiscardableHandleManager(discardableHandleManager) { |
| 268 | SkASSERT(fDiscardableHandleManager); |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 269 | } |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 270 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 271 | SkStrikeServer::~SkStrikeServer() = default; |
Herb Derby | 46117c8 | 2018-04-03 18:44:34 -0400 | [diff] [blame] | 272 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 273 | sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) { |
Khushal | 38c7a2e | 2018-10-16 13:50:34 -0700 | [diff] [blame] | 274 | auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf)); |
| 275 | if (data) { |
| 276 | return *data; |
| 277 | } |
| 278 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 279 | WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(), |
| 280 | tf->isFixedPitch()); |
Khushal | 38c7a2e | 2018-10-16 13:50:34 -0700 | [diff] [blame] | 281 | data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf), |
| 282 | SkData::MakeWithCopy(&wire, sizeof(wire))); |
| 283 | return *data; |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 284 | } |
| 285 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 286 | void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) { |
Herb Derby | aca2b9e | 2018-08-28 15:33:19 -0400 | [diff] [blame] | 287 | if (fLockedDescs.empty() && fTypefacesToSend.empty()) { |
| 288 | return; |
| 289 | } |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 290 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 291 | Serializer serializer(memory); |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 292 | serializer.emplace<uint64_t>(fTypefacesToSend.size()); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 293 | for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf); |
| 294 | fTypefacesToSend.clear(); |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 295 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 296 | serializer.emplace<uint64_t>(fLockedDescs.size()); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 297 | for (const auto* desc : fLockedDescs) { |
| 298 | auto it = fRemoteGlyphStateMap.find(desc); |
| 299 | SkASSERT(it != fRemoteGlyphStateMap.end()); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 300 | it->second->writePendingGlyphs(&serializer); |
| 301 | } |
| 302 | fLockedDescs.clear(); |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 303 | } |
| 304 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 305 | SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache( |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 306 | const SkPaint& paint, |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 307 | const SkFont& font, |
Herb Derby | c03716d | 2018-09-17 11:39:51 -0400 | [diff] [blame] | 308 | const SkSurfaceProps& props, |
| 309 | const SkMatrix& matrix, |
Khushal | 3e7548c | 2018-05-23 15:45:01 -0700 | [diff] [blame] | 310 | SkScalerContextFlags flags, |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 311 | SkScalerContextEffects* effects) { |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 312 | SkAutoDescriptor keyAutoDesc; |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 313 | auto keyDesc = create_descriptor( |
| 314 | kKey, paint, font, matrix, props, flags, &keyAutoDesc, effects); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 315 | |
| 316 | // In cases where tracing is turned off, make sure not to get an unused function warning. |
| 317 | // Lambdaize the function. |
| 318 | TRACE_EVENT1("skia", "RecForDesc", "rec", |
| 319 | TRACE_STR_COPY( |
| 320 | [keyDesc](){ |
| 321 | auto ptr = keyDesc->findEntry(kRec_SkDescriptorTag, nullptr); |
| 322 | SkScalerContextRec rec; |
| 323 | std::memcpy(&rec, ptr, sizeof(rec)); |
| 324 | return rec.dump(); |
| 325 | }().c_str() |
| 326 | ) |
| 327 | ); |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 328 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 329 | // Already locked. |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 330 | if (fLockedDescs.find(keyDesc) != fLockedDescs.end()) { |
| 331 | auto it = fRemoteGlyphStateMap.find(keyDesc); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 332 | SkASSERT(it != fRemoteGlyphStateMap.end()); |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 333 | SkGlyphCacheState* cache = it->second.get(); |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 334 | cache->setFontAndEffects(font, SkScalerContextEffects{paint}); |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 335 | return cache; |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 336 | } |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 337 | |
| 338 | // Try to lock. |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 339 | auto it = fRemoteGlyphStateMap.find(keyDesc); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 340 | if (it != fRemoteGlyphStateMap.end()) { |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 341 | SkGlyphCacheState* cache = it->second.get(); |
Khushal | 1c94a8f | 2018-07-23 13:40:37 -0700 | [diff] [blame] | 342 | #ifdef SK_DEBUG |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 343 | SkScalerContextEffects deviceEffects; |
| 344 | SkAutoDescriptor deviceAutoDesc; |
| 345 | auto deviceDesc = create_descriptor( |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 346 | kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects); |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 347 | SkASSERT(cache->getDeviceDescriptor() == *deviceDesc); |
Khushal | 1c94a8f | 2018-07-23 13:40:37 -0700 | [diff] [blame] | 348 | #endif |
Khushal | fa8ff09 | 2018-06-06 17:46:38 -0700 | [diff] [blame] | 349 | bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId()); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 350 | if (locked) { |
| 351 | fLockedDescs.insert(it->first); |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 352 | cache->setFontAndEffects(font, SkScalerContextEffects{paint}); |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 353 | return cache; |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | // If the lock failed, the entry was deleted on the client. Remove our |
| 357 | // tracking. |
| 358 | fRemoteGlyphStateMap.erase(it); |
| 359 | } |
| 360 | |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 361 | auto* tf = font.getTypeface(); |
Herb Derby | e1f566f | 2018-05-03 17:05:30 -0400 | [diff] [blame] | 362 | const SkFontID typefaceId = tf->uniqueID(); |
| 363 | if (!fCachedTypefaces.contains(typefaceId)) { |
| 364 | fCachedTypefaces.add(typefaceId); |
| 365 | fTypefacesToSend.emplace_back(typefaceId, tf->countGlyphs(), tf->fontStyle(), |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 366 | tf->isFixedPitch()); |
| 367 | } |
| 368 | |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 369 | SkScalerContextEffects deviceEffects; |
| 370 | SkAutoDescriptor deviceAutoDesc; |
| 371 | auto deviceDesc = create_descriptor( |
Herb Derby | e7f662b | 2018-12-17 12:12:56 -0500 | [diff] [blame] | 372 | kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 373 | |
| 374 | auto context = tf->createScalerContext(deviceEffects, deviceDesc); |
| 375 | |
Herb Derby | ee2a3f3 | 2018-08-24 11:43:58 -0400 | [diff] [blame] | 376 | // Create a new cache state and insert it into the map. |
Herb Derby | e1f566f | 2018-05-03 17:05:30 -0400 | [diff] [blame] | 377 | auto newHandle = fDiscardableHandleManager->createHandle(); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 378 | auto cacheState = skstd::make_unique<SkGlyphCacheState>( |
| 379 | *keyDesc, *deviceDesc, std::move(context), newHandle); |
| 380 | |
Herb Derby | e1f566f | 2018-05-03 17:05:30 -0400 | [diff] [blame] | 381 | auto* cacheStatePtr = cacheState.get(); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 382 | |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 383 | fLockedDescs.insert(&cacheStatePtr->getKeyDescriptor()); |
| 384 | fRemoteGlyphStateMap[&cacheStatePtr->getKeyDescriptor()] = std::move(cacheState); |
Khushal | cf33b1b | 2018-08-29 16:16:25 -0700 | [diff] [blame] | 385 | |
| 386 | checkForDeletedEntries(); |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 387 | |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 388 | cacheStatePtr->setFontAndEffects(font, SkScalerContextEffects{paint}); |
Herb Derby | e1f566f | 2018-05-03 17:05:30 -0400 | [diff] [blame] | 389 | return cacheStatePtr; |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 390 | } |
| 391 | |
Khushal | cf33b1b | 2018-08-29 16:16:25 -0700 | [diff] [blame] | 392 | void SkStrikeServer::checkForDeletedEntries() { |
| 393 | auto it = fRemoteGlyphStateMap.begin(); |
| 394 | while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap && |
| 395 | it != fRemoteGlyphStateMap.end()) { |
| 396 | if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) { |
| 397 | it = fRemoteGlyphStateMap.erase(it); |
| 398 | } else { |
| 399 | ++it; |
| 400 | } |
| 401 | } |
| 402 | } |
| 403 | |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 404 | // -- SkGlyphCacheState ---------------------------------------------------------------------------- |
| 405 | SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState( |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 406 | const SkDescriptor& keyDescriptor, |
| 407 | const SkDescriptor& deviceDescriptor, |
| 408 | std::unique_ptr<SkScalerContext> context, |
| 409 | uint32_t discardableHandleId) |
| 410 | : fKeyDescriptor{keyDescriptor} |
| 411 | , fDeviceDescriptor{deviceDescriptor} |
| 412 | , fDiscardableHandleId(discardableHandleId) |
| 413 | , fIsSubpixel{context->isSubpixel()} |
| 414 | , fAxisAlignmentForHText{context->computeAxisAlignmentForHText()} |
| 415 | // N.B. context must come last because it is used above. |
| 416 | , fContext{std::move(context)} { |
| 417 | SkASSERT(fKeyDescriptor.getDesc() != nullptr); |
| 418 | SkASSERT(fDeviceDescriptor.getDesc() != nullptr); |
| 419 | SkASSERT(fContext != nullptr); |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 420 | } |
| 421 | |
| 422 | SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default; |
| 423 | |
Herb Derby | b2c7216 | 2018-08-23 16:16:31 -0400 | [diff] [blame] | 424 | void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) { |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 425 | auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages; |
| 426 | auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages; |
| 427 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 428 | // Already cached. |
Herb Derby | aca2b9e | 2018-08-28 15:33:19 -0400 | [diff] [blame] | 429 | if (cache->contains(glyph)) { |
| 430 | return; |
| 431 | } |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 432 | |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 433 | // A glyph is going to be sent. Make sure we have a scaler context to send it. |
| 434 | this->ensureScalerContext(); |
| 435 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 436 | // Serialize and cache. Also create the scalar context to use when serializing |
| 437 | // this glyph. |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 438 | cache->add(glyph); |
| 439 | pending->push_back(glyph); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 440 | } |
| 441 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 442 | static void writeGlyph(SkGlyph* glyph, Serializer* serializer) { |
| 443 | serializer->write<SkPackedGlyphID>(glyph->getPackedID()); |
| 444 | serializer->write<float>(glyph->fAdvanceX); |
| 445 | serializer->write<float>(glyph->fAdvanceY); |
| 446 | serializer->write<uint16_t>(glyph->fWidth); |
| 447 | serializer->write<uint16_t>(glyph->fHeight); |
| 448 | serializer->write<int16_t>(glyph->fTop); |
| 449 | serializer->write<int16_t>(glyph->fLeft); |
| 450 | serializer->write<int8_t>(glyph->fForceBW); |
| 451 | serializer->write<uint8_t>(glyph->fMaskFormat); |
| 452 | } |
| 453 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 454 | void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) { |
Khushal | fa8ff09 | 2018-06-06 17:46:38 -0700 | [diff] [blame] | 455 | // TODO(khushalsagar): Write a strike only if it has any pending glyphs. |
| 456 | serializer->emplace<bool>(this->hasPendingGlyphs()); |
| 457 | if (!this->hasPendingGlyphs()) { |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 458 | this->resetScalerContext(); |
Khushal | fa8ff09 | 2018-06-06 17:46:38 -0700 | [diff] [blame] | 459 | return; |
| 460 | } |
| 461 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 462 | // Write the desc. |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 463 | serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 464 | serializer->writeDescriptor(*fKeyDescriptor.getDesc()); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 465 | |
| 466 | // Write FontMetrics. |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 467 | // TODO(khushalsagar): Do we need to re-send each time? |
Mike Reed | b5784ac | 2018-11-12 09:35:15 -0500 | [diff] [blame] | 468 | SkFontMetrics fontMetrics; |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 469 | fContext->getFontMetrics(&fontMetrics); |
Mike Reed | b5784ac | 2018-11-12 09:35:15 -0500 | [diff] [blame] | 470 | serializer->write<SkFontMetrics>(fontMetrics); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 471 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 472 | // Write glyphs images. |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 473 | serializer->emplace<uint64_t>(fPendingGlyphImages.size()); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 474 | for (const auto& glyphID : fPendingGlyphImages) { |
Herb Derby | f6fca26 | 2019-01-09 15:13:54 -0500 | [diff] [blame] | 475 | SkGlyph glyph{glyphID}; |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 476 | fContext->getMetrics(&glyph); |
| 477 | writeGlyph(&glyph, serializer); |
Khushal | 40adb3c | 2018-08-16 17:10:11 -0700 | [diff] [blame] | 478 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 479 | auto imageSize = glyph.computeImageSize(); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 480 | if (imageSize == 0u) continue; |
| 481 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 482 | glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment()); |
| 483 | fContext->getImage(glyph); |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 484 | // TODO: Generating the image can change the mask format, do we need to update it in the |
| 485 | // serialized glyph? |
Mike Klein | 8a23202 | 2018-05-02 13:54:11 +0000 | [diff] [blame] | 486 | } |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 487 | fPendingGlyphImages.clear(); |
| 488 | |
| 489 | // Write glyphs paths. |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 490 | serializer->emplace<uint64_t>(fPendingGlyphPaths.size()); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 491 | for (const auto& glyphID : fPendingGlyphPaths) { |
Herb Derby | f6fca26 | 2019-01-09 15:13:54 -0500 | [diff] [blame] | 492 | SkGlyph glyph{glyphID}; |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 493 | fContext->getMetrics(&glyph); |
| 494 | writeGlyph(&glyph, serializer); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 495 | writeGlyphPath(glyphID, serializer); |
| 496 | } |
| 497 | fPendingGlyphPaths.clear(); |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 498 | this->resetScalerContext(); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 499 | } |
| 500 | |
Herb Derby | b2c7216 | 2018-08-23 16:16:31 -0400 | [diff] [blame] | 501 | const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkPackedGlyphID glyphID) { |
Herb Derby | 4627523 | 2019-01-10 14:01:22 -0500 | [diff] [blame] | 502 | SkGlyph* glyphPtr = fGlyphMap.findOrNull(glyphID); |
| 503 | if (glyphPtr == nullptr) { |
| 504 | glyphPtr = fAlloc.make<SkGlyph>(glyphID); |
| 505 | fGlyphMap.set(glyphPtr); |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 506 | this->ensureScalerContext(); |
Herb Derby | 4627523 | 2019-01-10 14:01:22 -0500 | [diff] [blame] | 507 | fContext->getMetrics(glyphPtr); |
Khushal | fa8ff09 | 2018-06-06 17:46:38 -0700 | [diff] [blame] | 508 | } |
Herb Derby | b2c7216 | 2018-08-23 16:16:31 -0400 | [diff] [blame] | 509 | |
Herb Derby | 4627523 | 2019-01-10 14:01:22 -0500 | [diff] [blame] | 510 | return *glyphPtr; |
Khushal | fa8ff09 | 2018-06-06 17:46:38 -0700 | [diff] [blame] | 511 | } |
| 512 | |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 513 | void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() { |
| 514 | if (fContext == nullptr) { |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 515 | auto tf = fFont->getTypeface(); |
| 516 | fContext = tf->createScalerContext(fEffects, fDeviceDescriptor.getDesc()); |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 517 | } |
| 518 | } |
| 519 | |
Herb Derby | fc1cb22 | 2018-12-17 13:50:00 -0500 | [diff] [blame] | 520 | void SkStrikeServer::SkGlyphCacheState::resetScalerContext() { |
| 521 | fContext.reset(); |
| 522 | fFont = nullptr; |
| 523 | } |
| 524 | |
| 525 | void SkStrikeServer::SkGlyphCacheState::setFontAndEffects( |
| 526 | const SkFont& font, SkScalerContextEffects effects) { |
| 527 | fFont = &font; |
| 528 | fEffects = effects; |
Herb Derby | 48415e9 | 2018-09-11 17:29:53 -0400 | [diff] [blame] | 529 | } |
| 530 | |
Herb Derby | d2fec23 | 2018-08-23 18:44:45 -0400 | [diff] [blame] | 531 | SkVector SkStrikeServer::SkGlyphCacheState::rounding() const { |
| 532 | return SkGlyphCacheCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText); |
| 533 | } |
| 534 | |
| 535 | const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics( |
| 536 | SkGlyphID glyphID, SkPoint position) { |
| 537 | SkIPoint lookupPoint = SkGlyphCacheCommon::SubpixelLookup(fAxisAlignmentForHText, position); |
| 538 | SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint} |
| 539 | : SkPackedGlyphID{glyphID}; |
| 540 | |
| 541 | return this->findGlyph(packedGlyphID); |
| 542 | } |
| 543 | |
Herb Derby | 2d4f7cb | 2018-11-27 12:37:50 -0500 | [diff] [blame] | 544 | bool SkStrikeServer::SkGlyphCacheState::hasImage(const SkGlyph& glyph) { |
| 545 | // If a glyph has width and height, it must have an image available to it. |
| 546 | return !glyph.isEmpty(); |
| 547 | } |
| 548 | |
| 549 | bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) { |
| 550 | return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr; |
| 551 | } |
| 552 | |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 553 | void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID, |
| 554 | Serializer* serializer) const { |
| 555 | SkPath path; |
| 556 | if (!fContext->getPath(glyphID, &path)) { |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 557 | serializer->write<uint64_t>(0u); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 558 | return; |
| 559 | } |
| 560 | |
| 561 | size_t pathSize = path.writeToMemory(nullptr); |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 562 | serializer->write<uint64_t>(pathSize); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 563 | path.writeToMemory(serializer->allocate(pathSize, kPathAlignment)); |
| 564 | } |
| 565 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 566 | // SkStrikeClient ----------------------------------------- |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 567 | class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner { |
| 568 | public: |
| 569 | DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId, |
| 570 | sk_sp<DiscardableHandleManager> manager) |
| 571 | : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {} |
| 572 | |
| 573 | ~DiscardableStrikePinner() override = default; |
| 574 | bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); } |
| 575 | |
| 576 | private: |
| 577 | const SkDiscardableHandleId fDiscardableHandleId; |
| 578 | sk_sp<DiscardableHandleManager> fManager; |
| 579 | }; |
| 580 | |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 581 | SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager, |
| 582 | bool isLogging, |
| 583 | SkStrikeCache* strikeCache) |
Herb Derby | feb9fa9 | 2018-06-01 16:47:21 -0400 | [diff] [blame] | 584 | : fDiscardableHandleManager(std::move(discardableManager)) |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 585 | , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()} |
Herb Derby | feb9fa9 | 2018-06-01 16:47:21 -0400 | [diff] [blame] | 586 | , fIsLogging{isLogging} {} |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 587 | |
| 588 | SkStrikeClient::~SkStrikeClient() = default; |
| 589 | |
| 590 | #define READ_FAILURE \ |
| 591 | { \ |
| 592 | SkDEBUGFAIL("Bad serialization"); \ |
| 593 | return false; \ |
| 594 | } |
| 595 | |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 596 | static bool readGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) { |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 597 | SkPackedGlyphID glyphID; |
| 598 | if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false; |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 599 | glyph.init(glyphID); |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 600 | if (!deserializer->read<float>(&glyph->fAdvanceX)) return false; |
| 601 | if (!deserializer->read<float>(&glyph->fAdvanceY)) return false; |
| 602 | if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false; |
| 603 | if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false; |
| 604 | if (!deserializer->read<int16_t>(&glyph->fTop)) return false; |
| 605 | if (!deserializer->read<int16_t>(&glyph->fLeft)) return false; |
| 606 | if (!deserializer->read<int8_t>(&glyph->fForceBW)) return false; |
| 607 | if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false; |
| 608 | return true; |
| 609 | } |
| 610 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 611 | bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) { |
| 612 | SkASSERT(memorySize != 0u); |
| 613 | Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize); |
| 614 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 615 | uint64_t typefaceSize = 0u; |
| 616 | if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 617 | |
| 618 | for (size_t i = 0; i < typefaceSize; ++i) { |
| 619 | WireTypeface wire; |
| 620 | if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE |
| 621 | |
| 622 | // TODO(khushalsagar): The typeface no longer needs a reference to the |
| 623 | // SkStrikeClient, since all needed glyphs must have been pushed before |
| 624 | // raster. |
| 625 | addTypeface(wire); |
| 626 | } |
| 627 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 628 | uint64_t strikeCount = 0u; |
| 629 | if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 630 | |
| 631 | for (size_t i = 0; i < strikeCount; ++i) { |
| 632 | bool has_glyphs = false; |
| 633 | if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE |
| 634 | |
| 635 | if (!has_glyphs) continue; |
| 636 | |
| 637 | StrikeSpec spec; |
| 638 | if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE |
| 639 | |
| 640 | SkAutoDescriptor sourceAd; |
| 641 | if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE |
| 642 | |
Mike Reed | b5784ac | 2018-11-12 09:35:15 -0500 | [diff] [blame] | 643 | SkFontMetrics fontMetrics; |
| 644 | if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 645 | |
| 646 | // Get the local typeface from remote fontID. |
| 647 | auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get(); |
| 648 | // Received strikes for a typeface which doesn't exist. |
| 649 | if (!tf) READ_FAILURE |
| 650 | |
| 651 | // Replace the ContextRec in the desc from the server to create the client |
| 652 | // side descriptor. |
| 653 | // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy. |
| 654 | SkAutoDescriptor ad; |
| 655 | auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad); |
| 656 | |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 657 | auto strike = fStrikeCache->findStrikeExclusive(*client_desc); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 658 | if (strike == nullptr) { |
| 659 | // Note that we don't need to deserialize the effects since we won't be generating any |
| 660 | // glyphs here anyway, and the desc is still correct since it includes the serialized |
| 661 | // effects. |
| 662 | SkScalerContextEffects effects; |
| 663 | auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf); |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 664 | strike = fStrikeCache->createStrikeExclusive( |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 665 | *client_desc, std::move(scaler), &fontMetrics, |
| 666 | skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId, |
| 667 | fDiscardableHandleManager)); |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 668 | auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext()); |
| 669 | proxyContext->initCache(strike.get(), fStrikeCache); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 670 | } |
| 671 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 672 | uint64_t glyphImagesCount = 0u; |
| 673 | if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 674 | for (size_t j = 0; j < glyphImagesCount; j++) { |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 675 | SkTLazy<SkGlyph> glyph; |
| 676 | if (!readGlyph(glyph, &deserializer)) READ_FAILURE |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 677 | |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 678 | SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 679 | |
| 680 | // Update the glyph unless it's already got an image (from fallback), |
| 681 | // preserving any path that might be present. |
| 682 | if (allocatedGlyph->fImage == nullptr) { |
| 683 | auto* glyphPath = allocatedGlyph->fPathData; |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 684 | *allocatedGlyph = *glyph; |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 685 | allocatedGlyph->fPathData = glyphPath; |
| 686 | } |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 687 | |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 688 | auto imageSize = glyph->computeImageSize(); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 689 | if (imageSize == 0u) continue; |
| 690 | |
| 691 | auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment()); |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 692 | if (!image) READ_FAILURE |
| 693 | strike->initializeImage(image, imageSize, allocatedGlyph); |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 694 | } |
| 695 | |
Peter Collingbourne | 77b02f6 | 2018-07-16 16:41:47 -0700 | [diff] [blame] | 696 | uint64_t glyphPathsCount = 0u; |
| 697 | if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 698 | for (size_t j = 0; j < glyphPathsCount; j++) { |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 699 | SkTLazy<SkGlyph> glyph; |
| 700 | if (!readGlyph(glyph, &deserializer)) READ_FAILURE |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 701 | |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 702 | SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID()); |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 703 | |
| 704 | // Update the glyph unless it's already got a path (from fallback), |
| 705 | // preserving any image that might be present. |
| 706 | if (allocatedGlyph->fPathData == nullptr) { |
| 707 | auto* glyphImage = allocatedGlyph->fImage; |
Herb Derby | 811a672 | 2019-01-10 13:58:05 -0500 | [diff] [blame^] | 708 | *allocatedGlyph = *glyph; |
Khushal | 4010c79 | 2018-06-13 09:44:23 -0700 | [diff] [blame] | 709 | allocatedGlyph->fImage = glyphImage; |
| 710 | } |
Khushal | 51371a4 | 2018-05-17 10:41:40 -0700 | [diff] [blame] | 711 | |
| 712 | if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 713 | } |
| 714 | } |
| 715 | |
Ben Wagner | 5ddb308 | 2018-03-29 11:18:06 -0400 | [diff] [blame] | 716 | return true; |
Herb Derby | 97be88f | 2018-03-21 16:23:49 -0400 | [diff] [blame] | 717 | } |
| 718 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 719 | sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) { |
Herb Derby | b2922f6 | 2018-01-26 16:47:54 -0500 | [diff] [blame] | 720 | WireTypeface wire; |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 721 | if (len != sizeof(wire)) return nullptr; |
Herb Derby | b2922f6 | 2018-01-26 16:47:54 -0500 | [diff] [blame] | 722 | memcpy(&wire, buf, sizeof(wire)); |
Herb Derby | 5c0c798 | 2018-06-21 15:15:50 -0400 | [diff] [blame] | 723 | return this->addTypeface(wire); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 724 | } |
Herb Derby | 9d02182 | 2018-02-02 12:54:55 -0500 | [diff] [blame] | 725 | |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 726 | sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) { |
| 727 | auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID); |
| 728 | if (typeface) return *typeface; |
Herb Derby | b2922f6 | 2018-01-26 16:47:54 -0500 | [diff] [blame] | 729 | |
Herb Derby | feb9fa9 | 2018-06-01 16:47:21 -0400 | [diff] [blame] | 730 | auto newTypeface = sk_make_sp<SkTypefaceProxy>( |
| 731 | wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed, |
| 732 | fDiscardableHandleManager, fIsLogging); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 733 | fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface); |
Herb Derby | 16d4564 | 2018-05-03 10:52:02 -0400 | [diff] [blame] | 734 | return std::move(newTypeface); |
Khushal | 38a0843 | 2018-05-02 10:29:37 -0700 | [diff] [blame] | 735 | } |