blob: 2895fac678eaf38da769a183bead6abad91e6be9 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/text/gpu/SlugImpl.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSerialProcs.h"
#include "include/private/base/SkAssert.h"
#include "include/private/chromium/Slug.h"
#include "src/core/SkDevice.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"
#include "src/text/GlyphRun.h"
#include "src/text/gpu/SubRunAllocator.h"
#include "src/text/gpu/SubRunContainer.h"
#include <memory>
#include <utility>
class SkStrikeClient;
namespace sktext::gpu {
SlugImpl::SlugImpl(SubRunAllocator&& alloc,
gpu::SubRunContainerOwner subRuns,
SkRect sourceBounds,
SkPoint origin)
: fAlloc {std::move(alloc)}
, fSubRuns(std::move(subRuns))
, fSourceBounds{sourceBounds}
, fOrigin{origin} {}
void SlugImpl::doFlatten(SkWriteBuffer& buffer) const {
buffer.writeRect(fSourceBounds);
buffer.writePoint(fOrigin);
fSubRuns->flattenAllocSizeHint(buffer);
fSubRuns->flattenRuns(buffer);
}
sk_sp<Slug> SlugImpl::MakeFromBuffer(SkReadBuffer& buffer, const SkStrikeClient* client) {
SkRect sourceBounds = buffer.readRect();
if (!buffer.validate(!sourceBounds.isEmpty())) {
return nullptr;
}
SkPoint origin = buffer.readPoint();
int allocSizeHint = gpu::SubRunContainer::AllocSizeHintFromBuffer(buffer);
auto [initializer, _, alloc] =
SubRunAllocator::AllocateClassMemoryAndArena<SlugImpl>(allocSizeHint);
gpu::SubRunContainerOwner container =
gpu::SubRunContainer::MakeFromBufferInAlloc(buffer, client, &alloc);
// Something went wrong while reading.
if (!buffer.isValid()) {
return nullptr;
}
return sk_sp<SlugImpl>(
initializer.initialize(std::move(alloc), std::move(container), sourceBounds, origin));
}
SkMatrix position_matrix(const SkMatrix& drawMatrix, SkPoint drawOrigin) {
SkMatrix position_matrix = drawMatrix;
return position_matrix.preTranslate(drawOrigin.x(), drawOrigin.y());
}
sk_sp<SlugImpl> SlugImpl::Make(const SkMatrix& viewMatrix,
const sktext::GlyphRunList& glyphRunList,
const SkPaint& paint,
SkStrikeDeviceInfo strikeDeviceInfo,
sktext::StrikeForGPUCacheInterface* strikeCache) {
size_t subRunSizeHint = gpu::SubRunContainer::EstimateAllocSize(glyphRunList);
auto [initializer, _, alloc] =
SubRunAllocator::AllocateClassMemoryAndArena<SlugImpl>(subRunSizeHint);
const SkMatrix positionMatrix = position_matrix(viewMatrix, glyphRunList.origin());
auto subRuns = gpu::SubRunContainer::MakeInAlloc(glyphRunList,
positionMatrix,
paint,
strikeDeviceInfo,
strikeCache,
&alloc,
gpu::SubRunContainer::kAddSubRuns,
"Make Slug");
sk_sp<SlugImpl> slug = sk_sp<SlugImpl>(initializer.initialize(std::move(alloc),
std::move(subRuns),
glyphRunList.sourceBounds(),
glyphRunList.origin()));
// There is nothing to draw here. This is particularly a problem with RSX form blobs where a
// single space becomes a run with no glyphs.
if (slug->fSubRuns->isEmpty()) { return nullptr; }
return slug;
}
void Slug::AddDeserialProcs(SkDeserialProcs* procs, const SkStrikeClient* client) {
SkASSERT(procs);
procs->fSlugCtx = const_cast<SkStrikeClient*>(client);
procs->fSlugProc = [](SkReadBuffer& buffer, void* ctx) -> sk_sp<Slug> {
auto client = static_cast<const SkStrikeClient*>(ctx);
return SlugImpl::MakeFromBuffer(buffer, client);
};
}
} // namespace sktext::gpu