xref: /aosp_15_r20/external/skia/src/text/gpu/SlugImpl.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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