1 /*
2 * Copyright 2023 Google LLC
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 "src/text/gpu/SlugImpl.h"
9
10 #include "include/core/SkMatrix.h"
11 #include "include/core/SkPoint.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkSerialProcs.h"
14 #include "include/private/base/SkAssert.h"
15 #include "include/private/chromium/Slug.h"
16 #include "src/core/SkDevice.h"
17 #include "src/core/SkReadBuffer.h"
18 #include "src/core/SkWriteBuffer.h"
19 #include "src/text/GlyphRun.h"
20 #include "src/text/gpu/SubRunAllocator.h"
21 #include "src/text/gpu/SubRunContainer.h"
22
23 #include <memory>
24 #include <utility>
25
26 class SkStrikeClient;
27
28 namespace sktext::gpu {
29
SlugImpl(SubRunAllocator && alloc,gpu::SubRunContainerOwner subRuns,SkRect sourceBounds,SkPoint origin)30 SlugImpl::SlugImpl(SubRunAllocator&& alloc,
31 gpu::SubRunContainerOwner subRuns,
32 SkRect sourceBounds,
33 SkPoint origin)
34 : fAlloc {std::move(alloc)}
35 , fSubRuns(std::move(subRuns))
36 , fSourceBounds{sourceBounds}
37 , fOrigin{origin} {}
38
doFlatten(SkWriteBuffer & buffer) const39 void SlugImpl::doFlatten(SkWriteBuffer& buffer) const {
40 buffer.writeRect(fSourceBounds);
41 buffer.writePoint(fOrigin);
42 fSubRuns->flattenAllocSizeHint(buffer);
43 fSubRuns->flattenRuns(buffer);
44 }
45
MakeFromBuffer(SkReadBuffer & buffer,const SkStrikeClient * client)46 sk_sp<Slug> SlugImpl::MakeFromBuffer(SkReadBuffer& buffer, const SkStrikeClient* client) {
47 SkRect sourceBounds = buffer.readRect();
48 if (!buffer.validate(!sourceBounds.isEmpty())) {
49 return nullptr;
50 }
51 SkPoint origin = buffer.readPoint();
52 int allocSizeHint = gpu::SubRunContainer::AllocSizeHintFromBuffer(buffer);
53
54 auto [initializer, _, alloc] =
55 SubRunAllocator::AllocateClassMemoryAndArena<SlugImpl>(allocSizeHint);
56
57 gpu::SubRunContainerOwner container =
58 gpu::SubRunContainer::MakeFromBufferInAlloc(buffer, client, &alloc);
59
60 // Something went wrong while reading.
61 if (!buffer.isValid()) {
62 return nullptr;
63 }
64
65 return sk_sp<SlugImpl>(
66 initializer.initialize(std::move(alloc), std::move(container), sourceBounds, origin));
67 }
68
position_matrix(const SkMatrix & drawMatrix,SkPoint drawOrigin)69 SkMatrix position_matrix(const SkMatrix& drawMatrix, SkPoint drawOrigin) {
70 SkMatrix position_matrix = drawMatrix;
71 return position_matrix.preTranslate(drawOrigin.x(), drawOrigin.y());
72 }
73
Make(const SkMatrix & viewMatrix,const sktext::GlyphRunList & glyphRunList,const SkPaint & paint,SkStrikeDeviceInfo strikeDeviceInfo,sktext::StrikeForGPUCacheInterface * strikeCache)74 sk_sp<SlugImpl> SlugImpl::Make(const SkMatrix& viewMatrix,
75 const sktext::GlyphRunList& glyphRunList,
76 const SkPaint& paint,
77 SkStrikeDeviceInfo strikeDeviceInfo,
78 sktext::StrikeForGPUCacheInterface* strikeCache) {
79 size_t subRunSizeHint = gpu::SubRunContainer::EstimateAllocSize(glyphRunList);
80 auto [initializer, _, alloc] =
81 SubRunAllocator::AllocateClassMemoryAndArena<SlugImpl>(subRunSizeHint);
82
83 const SkMatrix positionMatrix = position_matrix(viewMatrix, glyphRunList.origin());
84
85 auto subRuns = gpu::SubRunContainer::MakeInAlloc(glyphRunList,
86 positionMatrix,
87 paint,
88 strikeDeviceInfo,
89 strikeCache,
90 &alloc,
91 gpu::SubRunContainer::kAddSubRuns,
92 "Make Slug");
93
94 sk_sp<SlugImpl> slug = sk_sp<SlugImpl>(initializer.initialize(std::move(alloc),
95 std::move(subRuns),
96 glyphRunList.sourceBounds(),
97 glyphRunList.origin()));
98
99 // There is nothing to draw here. This is particularly a problem with RSX form blobs where a
100 // single space becomes a run with no glyphs.
101 if (slug->fSubRuns->isEmpty()) { return nullptr; }
102
103 return slug;
104 }
105
AddDeserialProcs(SkDeserialProcs * procs,const SkStrikeClient * client)106 void Slug::AddDeserialProcs(SkDeserialProcs* procs, const SkStrikeClient* client) {
107 SkASSERT(procs);
108 procs->fSlugCtx = const_cast<SkStrikeClient*>(client);
109 procs->fSlugProc = [](SkReadBuffer& buffer, void* ctx) -> sk_sp<Slug> {
110 auto client = static_cast<const SkStrikeClient*>(ctx);
111 return SlugImpl::MakeFromBuffer(buffer, client);
112 };
113 }
114
115 } // namespace sktext::gpu
116