summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h
blob: 86cbcac380a0de35484ea5e888d6bbcac406259a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_BLOBERIZER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_BLOBERIZER_H_

#include "third_party/blink/renderer/platform/fonts/canvas_rotation_in_vertical.h"
#include "third_party/blink/renderer/platform/fonts/glyph.h"
#include "third_party/blink/renderer/platform/fonts/paint_text_blob.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkTextBlob.h"

namespace blink {

class Font;
struct TextRunPaintInfo;

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&,
                              unsigned from,
                              unsigned to,
                              const GlyphData& emphasis_data,
                              const ShapeResult*);
  void Add(Glyph glyph,
           const SimpleFontData* font_data,
           CanvasRotationInVertical canvas_rotation,
           float h_offset) {
    // cannot mix x-only/xy offsets
    DCHECK(!HasPendingVerticalOffsets());

    if (UNLIKELY(font_data != pending_font_data_) ||
        UNLIKELY(canvas_rotation != pending_canvas_rotation_)) {
      CommitPendingRun();
      pending_font_data_ = font_data;
      pending_canvas_rotation_ = canvas_rotation;
      DCHECK_EQ(canvas_rotation, CanvasRotationInVertical::kRegular);
    }

    pending_glyphs_.push_back(glyph);
    pending_offsets_.push_back(h_offset);
  }

  void Add(Glyph glyph,
           const SimpleFontData* font_data,
           CanvasRotationInVertical canvas_rotation,
           const FloatPoint& offset) {
    // cannot mix x-only/xy offsets
    DCHECK(pending_glyphs_.IsEmpty() || HasPendingVerticalOffsets());

    if (UNLIKELY(font_data != pending_font_data_) ||
        UNLIKELY(canvas_rotation != pending_canvas_rotation_)) {
      CommitPendingRun();
      pending_font_data_ = font_data;
      pending_canvas_rotation_ = canvas_rotation;
      pending_vertical_baseline_x_offset_ =
          canvas_rotation == CanvasRotationInVertical::kRegular
              ? 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());
  }

  struct BlobInfo {
    BlobInfo(scoped_refptr<PaintTextBlob> b, CanvasRotationInVertical r)
        : blob(std::move(b)), rotation(r) {}
    scoped_refptr<PaintTextBlob> blob;
    CanvasRotationInVertical rotation;
  };

  using BlobBuffer = Vector<BlobInfo, 16>;
  const BlobBuffer& Blobs();

 private:
  friend class ShapeResultBloberizerTestInfo;

  float FillGlyphsForResult(const ShapeResult*,
                            const StringView&,
                            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);
  bool CanUseFastPath(unsigned from, unsigned to, const ShapeResult*);
  float FillFastHorizontalGlyphs(const ShapeResultBuffer&, TextDirection);
  float FillFastHorizontalGlyphs(const ShapeResult*, float advance = 0);

  void CommitPendingRun();
  void CommitPendingBlob();

  bool HasPendingVerticalOffsets() const;

  const Font& font_;
  const float device_scale_factor_;
  const Type type_;

  // Current text blob state.
  PaintTextBlobBuilder builder_;
  CanvasRotationInVertical builder_rotation_ =
      CanvasRotationInVertical::kRegular;
  size_t builder_run_count_ = 0;

  // Current run state.
  const SimpleFontData* pending_font_data_ = nullptr;
  CanvasRotationInVertical pending_canvas_rotation_ =
      CanvasRotationInVertical::kRegular;
  Vector<Glyph, 1024> pending_glyphs_;
  Vector<float, 1024> pending_offsets_;
  float pending_vertical_baseline_x_offset_ = 0;

  // Constructed blobs.
  BlobBuffer blobs_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_BLOBERIZER_H_