1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 #include "SkShaper.h"
8 #include "SkStream.h"
9 #include "SkTextBlob.h"
10 #include "SkTypeface.h"
11
12 struct SkShaper::Impl {
13 sk_sp<SkTypeface> fTypeface;
14 };
15
SkShaper(sk_sp<SkTypeface> tf)16 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
17 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
18 }
19
~SkShaper()20 SkShaper::~SkShaper() {}
21
good() const22 bool SkShaper::good() const { return true; }
23
24 // This example only uses public API, so we don't use SkUTF8_NextUnichar.
utf8_lead_byte_to_count(const char * ptr)25 unsigned utf8_lead_byte_to_count(const char* ptr) {
26 uint8_t c = *(const uint8_t*)ptr;
27 SkASSERT(c <= 0xF7);
28 SkASSERT((c & 0xC0) != 0x80);
29 return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
30 }
31
shape(SkTextBlobBuilder * builder,const SkPaint & srcPaint,const char * utf8text,size_t textBytes,bool leftToRight,SkPoint point,SkScalar width) const32 SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
33 const SkPaint& srcPaint,
34 const char* utf8text,
35 size_t textBytes,
36 bool leftToRight,
37 SkPoint point,
38 SkScalar width) const {
39 sk_ignore_unused_variable(leftToRight);
40
41 SkPaint paint(srcPaint);
42 paint.setTypeface(fImpl->fTypeface);
43 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
44 int glyphCount = paint.countText(utf8text, textBytes);
45 if (glyphCount <= 0) {
46 return point;
47 }
48 SkRect bounds;
49 SkPaint::FontMetrics metrics;
50 paint.getFontMetrics(&metrics);
51 point.fY -= metrics.fAscent;
52 (void)paint.measureText(utf8text, textBytes, &bounds);
53 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
54 const SkTextBlobBuilder::RunBuffer& runBuffer =
55 builder->allocRunTextPosH(paint, glyphCount, point.y(), textBytes, SkString(), &bounds);
56 memcpy(runBuffer.utf8text, utf8text, textBytes);
57 const char* txtPtr = utf8text;
58 for (int i = 0; i < glyphCount; ++i) {
59 // Each charater maps to exactly one glyph via SkGlyphCache::unicharToGlyph().
60 runBuffer.clusters[i] = SkToU32(txtPtr - utf8text);
61 txtPtr += utf8_lead_byte_to_count(txtPtr);
62 SkASSERT(txtPtr <= utf8text + textBytes);
63 }
64 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
65 (void)paint.textToGlyphs(utf8text, textBytes, runBuffer.glyphs);
66 (void)paint.getTextWidths(utf8text, textBytes, runBuffer.pos);
67 SkScalar x = point.x();
68 for (int i = 0; i < glyphCount; ++i) {
69 SkScalar w = runBuffer.pos[i];
70 runBuffer.pos[i] = x;
71 x += w;
72 }
73 point.fY += metrics.fDescent + metrics.fLeading;
74
75 return point;
76 }
77