37 for (
int index = 0; index < intersections.
size(); index += 2) {
39 end = intersections[index + 1] + uWidth;
40 if (
start > last && last + textSize / 12 <
start) {
41 underline.
moveTo(last, uPos);
48 underline.
lineTo(finalPos, uPos);
56 const size_t textLen = strlen(
text);
69 const int defaultRunLen = glyphCount / 3;
75 for (
int i = 0; i < defaultRunLen; ++i) {
76 advance +=
widths[glyphIndex++];
82 const int horizontalRunLen = glyphCount / 3;
87 SkTo<uint32_t>(horizontalRunLen) *
sizeof(
SkGlyphID));
88 for (
int i = 0; i < horizontalRunLen; ++i) {
90 advance +=
widths[glyphIndex++];
96 const int fullRunLen = glyphCount - glyphIndex;
99 SkTo<uint32_t>(fullRunLen) *
sizeof(
SkGlyphID));
100 for (
int i = 0; i < fullRunLen; ++i) {
101 buf.
pos[i * 2 + 0] = advance;
102 buf.
pos[i * 2 + 1] = 0;
103 advance +=
widths[glyphIndex++];
107 return blobBuilder.
make();
114 paint.setAntiAlias(
true);
115 const char* fam[] = {
"sans-serif",
"serif",
"monospace" };
116 const char test[] =
"aAjJgGyY_|{-(~[,]qQ}pP}zZ";
117 const SkPoint blobOffset = { 10, 80 };
119 for (
size_t font = 0; font < std::size(fam); ++font) {
120 for (
SkScalar textSize = 100; textSize > 10; textSize -= 20) {
122 const SkScalar uWidth = textSize / 15;
123 paint.setStrokeWidth(uWidth);
127 canvas->drawTextBlob(blob, blobOffset.
x(), blobOffset.
y(),
paint);
130 const SkScalar bounds[2] = { uPos - uWidth / 2, uPos + uWidth / 2 };
131 const int interceptCount = blob->getIntercepts(bounds,
nullptr, &
paint);
135 intercepts.
resize(interceptCount);
136 blob->getIntercepts(bounds, intercepts.
begin(), &
paint);
141 underline.
offset(blobOffset.
x(), blobOffset.
y());
143 canvas->drawPath(underline,
paint);
145 canvas->translate(0, textSize * 1.3f);
148 canvas->translate(0, 60);
163 for (
int i = 1; i <
count; ++i) {
164 xpos[i] += spacing * i;
174 for (
int i = 1; i <
count; ++i) {
175 pos[i].
fX += spacing * i;
187 *intervals++ -= margin;
188 while (intervals < stop - 1) {
189 intervals[0] += margin;
190 intervals[1] -= margin;
191 if (intervals[0] >= intervals[1]) {
192 int remaining = stop - intervals - 2;
193 SkASSERT(remaining >= 0 && (remaining & 1) == 1);
195 memmove(intervals, intervals + 2, remaining *
sizeof(
SkScalar));
203 *intervals += margin;
212 const SkScalar yminmax[] = { 8, 16 };
213 int count = blob->getIntercepts(yminmax,
nullptr);
219 blob->getIntercepts(yminmax, intervals.
get());
227 for (
int i = 0; i <
count; i += 2) {
228 path.lineTo(intervals[i],
y).moveTo(intervals[i+1],
y);
234 paint.setAntiAlias(
true);
236 paint.setStrokeWidth(yminmax[1] - yminmax[0]);
241 const char text[] =
"Hyjay {worlp}.";
252 canvas->translate(20, 120);
254 for (
SkScalar spacing = 0; spacing < 30; spacing += 20) {
257 canvas->translate(0, 150);
259 canvas->translate(0, 150);
@ kUTF8
uses bytes to represent UTF-8 or ASCII
@ kGlyphID
uses two byte words to represent glyph indices
#define SkScalarAve(a, b)
void drawPath(const SkPath &path, const SkPaint &paint)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
@ kAntiAlias
may have transparent pixels on glyph edges
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
void offset(SkScalar dx, SkScalar dy, SkPath *dst) const
SkPath & moveTo(SkScalar x, SkScalar y)
SkPath & lineTo(SkScalar x, SkScalar y)
const RunBuffer & allocRunPosH(const SkFont &font, int count, SkScalar y, const SkRect *bounds=nullptr)
const RunBuffer & allocRun(const SkFont &font, int count, SkScalar x, SkScalar y, const SkRect *bounds=nullptr)
sk_sp< SkTextBlob > make()
const RunBuffer & allocRunPos(const SkFont &font, int count, const SkRect *bounds=nullptr)
static sk_sp< SkTextBlob > MakeFromPosTextH(const void *text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
static sk_sp< SkTextBlob > MakeFromPosText(const void *text, size_t byteLength, const SkPoint pos[], const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
font
Font Metadata and Metrics.
constexpr float y() const
constexpr float x() const
SkScalar * pos
storage for glyph positions in run
SkGlyphID * glyphs
storage for glyph indexes in run
static void draw_blob_adorned(SkCanvas *canvas, sk_sp< SkTextBlob > blob)
static sk_sp< SkTextBlob > make_text(const SkFont &font, const SkGlyphID glyphs[], int count)
static SkPath create_underline(const SkTDArray< SkScalar > &intersections, SkScalar last, SkScalar finalPos, SkScalar uPos, SkScalar uWidth, SkScalar textSize)
static int trim_with_halo(SkScalar intervals[], int count, SkScalar margin)
static sk_sp< SkTextBlob > make_posh(const SkFont &font, const SkGlyphID glyphs[], int count, SkScalar spacing)
static sk_sp< SkTextBlob > make_pos(const SkFont &font, const SkGlyphID glyphs[], int count, SkScalar spacing)