blob: 78348675ae8a2f4060392b6d1424956493ac130a [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ShapeResultBloberizer_h
#define ShapeResultBloberizer_h
#include "platform/PlatformExport.h"
#include "platform/fonts/Glyph.h"
#include "platform/fonts/SimpleFontData.h"
#include "platform/fonts/shaping/ShapeResultBuffer.h"
#include "platform/geometry/FloatPoint.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/Vector.h"
#include "third_party/skia/include/core/SkTextBlob.h"
namespace blink {
class Font;
class PLATFORM_EXPORT ShapeResultBloberizer {
WTF_MAKE_NONCOPYABLE(ShapeResultBloberizer);
STACK_ALLOCATED();
public:
enum class Type { kNormal, kTextIntercepts };
ShapeResultBloberizer(const Font&,
float device_scale_factor,
Type = Type::kNormal);
Type GetType() const { return type_; }
float FillGlyphs(const TextRunPaintInfo&, const ShapeResultBuffer&);
float FillGlyphs(const StringView&,
unsigned from,
unsigned to,
const ShapeResult*);
void FillTextEmphasisGlyphs(const TextRunPaintInfo&,
const GlyphData& emphasis_data,
const ShapeResultBuffer&);
void FillTextEmphasisGlyphs(const StringView&,
TextDirection,
unsigned from,
unsigned to,
const GlyphData& emphasis_data,
const ShapeResult*);
void Add(Glyph glyph, const SimpleFontData* font_data, float h_offset) {
// cannot mix x-only/xy offsets
DCHECK(!HasPendingVerticalOffsets());
if (UNLIKELY(font_data != pending_font_data_)) {
CommitPendingRun();
pending_font_data_ = font_data;
DCHECK_EQ(GetBlobRotation(font_data), BlobRotation::kNoRotation);
}
pending_glyphs_.push_back(glyph);
pending_offsets_.push_back(h_offset);
}
void Add(Glyph glyph,
const SimpleFontData* font_data,
const FloatPoint& offset) {
// cannot mix x-only/xy offsets
DCHECK(pending_glyphs_.IsEmpty() || HasPendingVerticalOffsets());
if (UNLIKELY(font_data != pending_font_data_)) {
CommitPendingRun();
pending_font_data_ = font_data;
pending_vertical_baseline_x_offset_ =
GetBlobRotation(font_data) == BlobRotation::kNoRotation
? 0
: font_data->GetFontMetrics().FloatAscent() -
font_data->GetFontMetrics().FloatAscent(
kIdeographicBaseline);
}
pending_glyphs_.push_back(glyph);
pending_offsets_.push_back(offset.X() +
pending_vertical_baseline_x_offset_);
pending_offsets_.push_back(offset.Y());
}
enum class BlobRotation { kNoRotation, kCCWRotation };
struct BlobInfo {
BlobInfo(sk_sp<SkTextBlob> b, BlobRotation r)
: blob(std::move(b)), rotation(r) {}
sk_sp<SkTextBlob> blob;
BlobRotation rotation;
};
using BlobBuffer = Vector<BlobInfo, 16>;
const BlobBuffer& Blobs();
private:
friend class ShapeResultBloberizerTestInfo;
// Where TextContainerType can be either a TextRun or a StringView.
// For legacy layout and LayoutNG respectively.
template <typename TextContainerType>
float FillGlyphsForResult(const ShapeResult*,
const TextContainerType&,
unsigned from,
unsigned to,
float initial_advance,
unsigned run_offset);
// Whether the FillFastHorizontalGlyphs can be used. Only applies for full
// runs with no vertical offsets and no text intercepts.
bool CanUseFastPath(unsigned from,
unsigned to,
unsigned length,
bool has_vertical_offsets);
float FillFastHorizontalGlyphs(const ShapeResultBuffer&, TextDirection);
float FillFastHorizontalGlyphs(const ShapeResult*, float advance = 0);
template <typename TextContainerType>
float FillTextEmphasisGlyphsForRun(const ShapeResult::RunInfo*,
const TextContainerType&,
unsigned text_length,
TextDirection,
unsigned from,
unsigned to,
const GlyphData& emphasis_data,
float initial_advance,
unsigned run_offset);
void CommitPendingRun();
void CommitPendingBlob();
bool HasPendingVerticalOffsets() const;
static BlobRotation GetBlobRotation(const SimpleFontData*);
const Font& font_;
const float device_scale_factor_;
const Type type_;
// Current text blob state.
SkTextBlobBuilder builder_;
BlobRotation builder_rotation_ = BlobRotation::kNoRotation;
size_t builder_run_count_ = 0;
// Current run state.
const SimpleFontData* pending_font_data_ = nullptr;
Vector<Glyph, 1024> pending_glyphs_;
Vector<float, 1024> pending_offsets_;
float pending_vertical_baseline_x_offset_ = 0;
// Constructed blobs.
BlobBuffer blobs_;
};
} // namespace blink
#endif // ShapeResultBloberizer_h