Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions
texteffects.cpp File Reference
#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTDArray.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"
#include <string.h>

Go to the source code of this file.

Functions

static SkPath create_underline (const SkTDArray< SkScalar > &intersections, SkScalar last, SkScalar finalPos, SkScalar uPos, SkScalar uWidth, SkScalar textSize)
 
 DEF_SIMPLE_GM (fancyblobunderline, canvas, 1480, 1380)
 
static sk_sp< SkTextBlobmake_text (const SkFont &font, const SkGlyphID glyphs[], int count)
 
static sk_sp< SkTextBlobmake_posh (const SkFont &font, const SkGlyphID glyphs[], int count, SkScalar spacing)
 
static sk_sp< SkTextBlobmake_pos (const SkFont &font, const SkGlyphID glyphs[], int count, SkScalar spacing)
 
static int trim_with_halo (SkScalar intervals[], int count, SkScalar margin)
 
static void draw_blob_adorned (SkCanvas *canvas, sk_sp< SkTextBlob > blob)
 
 DEF_SIMPLE_GM (textblob_intercepts, canvas, 940, 800)
 

Function Documentation

◆ create_underline()

static SkPath create_underline ( const SkTDArray< SkScalar > &  intersections,
SkScalar  last,
SkScalar  finalPos,
SkScalar  uPos,
SkScalar  uWidth,
SkScalar  textSize 
)
static

Definition at line 32 of file texteffects.cpp.

34 {
35 SkPath underline;
36 SkScalar end = last;
37 for (int index = 0; index < intersections.size(); index += 2) {
38 SkScalar start = intersections[index] - uWidth;
39 end = intersections[index + 1] + uWidth;
40 if (start > last && last + textSize / 12 < start) {
41 underline.moveTo(last, uPos);
42 underline.lineTo(start, uPos);
43 }
44 last = end;
45 }
46 if (end < finalPos) {
47 underline.moveTo(end, uPos);
48 underline.lineTo(finalPos, uPos);
49 }
50 return underline;
51}
SkPath & moveTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:678
SkPath & lineTo(SkScalar x, SkScalar y)
Definition SkPath.cpp:718
int size() const
Definition SkTDArray.h:138
float SkScalar
Definition extension.cpp:12
glong glong end

◆ DEF_SIMPLE_GM() [1/2]

DEF_SIMPLE_GM ( fancyblobunderline  ,
canvas  ,
1480  ,
1380   
)

Definition at line 112 of file texteffects.cpp.

112 {
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 };
118
119 for (size_t font = 0; font < std::size(fam); ++font) {
120 for (SkScalar textSize = 100; textSize > 10; textSize -= 20) {
121 SkFont skFont(ToolUtils::CreatePortableTypeface(fam[font], SkFontStyle()), textSize);
122 const SkScalar uWidth = textSize / 15;
123 paint.setStrokeWidth(uWidth);
124 paint.setStyle(SkPaint::kFill_Style);
125
126 sk_sp<SkTextBlob> blob = MakeFancyBlob(paint, skFont, test);
127 canvas->drawTextBlob(blob, blobOffset.x(), blobOffset.y(), paint);
128
129 const SkScalar uPos = uWidth;
130 const SkScalar bounds[2] = { uPos - uWidth / 2, uPos + uWidth / 2 };
131 const int interceptCount = blob->getIntercepts(bounds, nullptr, &paint);
132 SkASSERT(!(interceptCount % 2));
133
134 SkTDArray<SkScalar> intercepts;
135 intercepts.resize(interceptCount);
136 blob->getIntercepts(bounds, intercepts.begin(), &paint);
137
138 const SkScalar start = blob->bounds().left();
139 const SkScalar end = blob->bounds().right();
140 SkPath underline = create_underline(intercepts, start, end, uPos, uWidth, textSize);
141 underline.offset(blobOffset.x(), blobOffset.y());
143 canvas->drawPath(underline, paint);
144
145 canvas->translate(0, textSize * 1.3f);
146 }
147
148 canvas->translate(0, 60);
149 }
150}
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kStroke_Style
set to stroke geometry
Definition SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
void offset(SkScalar dx, SkScalar dy, SkPath *dst) const
Definition SkPath.cpp:1627
T * begin()
Definition SkTDArray.h:150
void resize(int count)
Definition SkTDArray.h:183
const Paint & paint
Optional< SkRect > bounds
Definition SkRecords.h:189
sk_sp< SkTypeface > CreatePortableTypeface(const char *name, SkFontStyle style)
font
Font Metadata and Metrics.
constexpr float y() const
constexpr float x() const
static SkPath create_underline(const SkTDArray< SkScalar > &intersections, SkScalar last, SkScalar finalPos, SkScalar uPos, SkScalar uWidth, SkScalar textSize)

◆ DEF_SIMPLE_GM() [2/2]

DEF_SIMPLE_GM ( textblob_intercepts  ,
canvas  ,
940  ,
800   
)

Definition at line 240 of file texteffects.cpp.

240 {
241 const char text[] = "Hyjay {worlp}.";
242 const size_t length = strlen(text);
244 font.setSize(100);
246 const int count = font.countText(text, length, SkTextEncoding::kUTF8);
248 font.textToGlyphs(text, length, SkTextEncoding::kUTF8, glyphs.get(), count);
249
250 auto b0 = make_text(font, glyphs.get(), count);
251
252 canvas->translate(20, 120);
253 draw_blob_adorned(canvas, b0);
254 for (SkScalar spacing = 0; spacing < 30; spacing += 20) {
255 auto b1 = make_posh(font, glyphs.get(), count, spacing);
256 auto b2 = make_pos( font, glyphs.get(), count, spacing);
257 canvas->translate(0, 150);
258 draw_blob_adorned(canvas, b1);
259 canvas->translate(0, 150);
260 draw_blob_adorned(canvas, b2);
261 }
262}
uint16_t glyphs[5]
int count
@ kUTF8
uses bytes to represent UTF-8 or ASCII
@ kAntiAlias
may have transparent pixels on glyph edges
size_t length
std::u16string text
SkFont DefaultPortableFont()
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 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)

◆ draw_blob_adorned()

static void draw_blob_adorned ( SkCanvas canvas,
sk_sp< SkTextBlob blob 
)
static

Definition at line 207 of file texteffects.cpp.

207 {
209
210 canvas->drawTextBlob(blob.get(), 0, 0, paint);
211
212 const SkScalar yminmax[] = { 8, 16 };
213 int count = blob->getIntercepts(yminmax, nullptr);
214 if (!count) {
215 return;
216 }
217
218 AutoTArray<SkScalar> intervals(count);
219 blob->getIntercepts(yminmax, intervals.get());
220 count = trim_with_halo(intervals.get(), count, SkScalarHalf(yminmax[1] - yminmax[0]) * 1.5f);
221 SkASSERT(count >= 2);
222
223 const SkScalar y = SkScalarAve(yminmax[0], yminmax[1]);
224 SkScalar end = 900;
225 SkPath path;
226 path.moveTo({0, y});
227 for (int i = 0; i < count; i += 2) {
228 path.lineTo(intervals[i], y).moveTo(intervals[i+1], y);
229 }
230 if (intervals[count - 1] < end) {
231 path.lineTo(end, y);
232 }
233
234 paint.setAntiAlias(true);
236 paint.setStrokeWidth(yminmax[1] - yminmax[0]);
237 canvas->drawPath(path, paint);
238}
#define SkScalarHalf(a)
Definition SkScalar.h:75
#define SkScalarAve(a, b)
Definition SkScalar.h:74
void drawPath(const SkPath &path, const SkPaint &paint)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
int getIntercepts(const SkScalar bounds[2], SkScalar intervals[], const SkPaint *paint=nullptr) const
T * get() const
Definition SkRefCnt.h:303
double y
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switches.h:57
static int trim_with_halo(SkScalar intervals[], int count, SkScalar margin)

◆ make_pos()

static sk_sp< SkTextBlob > make_pos ( const SkFont font,
const SkGlyphID  glyphs[],
int  count,
SkScalar  spacing 
)
static

Definition at line 170 of file texteffects.cpp.

171 {
173 font.getPos(glyphs, count, pos.get());
174 for (int i = 1; i < count; ++i) {
175 pos[i].fX += spacing * i;
176 }
177 return SkTextBlob::MakeFromPosText(glyphs, count * sizeof(SkGlyphID), pos.get(), font,
179}
SkPoint pos
@ kGlyphID
uses two byte words to represent glyph indices
uint16_t SkGlyphID
Definition SkTypes.h:179
static sk_sp< SkTextBlob > MakeFromPosText(const void *text, size_t byteLength, const SkPoint pos[], const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
float fX
x-axis value

◆ make_posh()

static sk_sp< SkTextBlob > make_posh ( const SkFont font,
const SkGlyphID  glyphs[],
int  count,
SkScalar  spacing 
)
static

Definition at line 159 of file texteffects.cpp.

160 {
162 font.getXPos(glyphs, count, xpos.get());
163 for (int i = 1; i < count; ++i) {
164 xpos[i] += spacing * i;
165 }
166 return SkTextBlob::MakeFromPosTextH(glyphs, count * sizeof(SkGlyphID), xpos.get(), 0, font,
168}
static sk_sp< SkTextBlob > MakeFromPosTextH(const void *text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)

◆ make_text()

static sk_sp< SkTextBlob > make_text ( const SkFont font,
const SkGlyphID  glyphs[],
int  count 
)
static

Definition at line 154 of file texteffects.cpp.

154 {
155 return SkTextBlob::MakeFromText(glyphs, count * sizeof(SkGlyphID), font,
157}
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)

◆ trim_with_halo()

static int trim_with_halo ( SkScalar  intervals[],
int  count,
SkScalar  margin 
)
static

Definition at line 182 of file texteffects.cpp.

182 {
183 SkASSERT(count > 0 && (count & 1) == 0);
184
185 int n = count;
186 SkScalar* stop = intervals + count;
187 *intervals++ -= margin;
188 while (intervals < stop - 1) {
189 intervals[0] += margin;
190 intervals[1] -= margin;
191 if (intervals[0] >= intervals[1]) { // went away
192 int remaining = stop - intervals - 2;
193 SkASSERT(remaining >= 0 && (remaining & 1) == 1);
194 if (remaining > 0) {
195 memmove(intervals, intervals + 2, remaining * sizeof(SkScalar));
196 }
197 stop -= 2;
198 n -= 2;
199 } else {
200 intervals += 2;
201 }
202 }
203 *intervals += margin;
204 return n;
205}