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 16 SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) { 17 fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault(); 18 } 19 20 SkShaper::~SkShaper() {} 21 22 bool SkShaper::good() const { return true; } 23 24 // This example only uses public API, so we don't use SkUTF8_NextUnichar. 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 32 SkScalar SkShaper::shape(SkTextBlobBuilder* builder, 33 const SkPaint& srcPaint, 34 const char* utf8text, 35 size_t textBytes, 36 SkPoint point) const { 37 SkPaint paint(srcPaint); 38 paint.setTypeface(fImpl->fTypeface); 39 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); 40 int glyphCount = paint.countText(utf8text, textBytes); 41 if (glyphCount <= 0) { 42 return 0; 43 } 44 SkRect bounds; 45 (void)paint.measureText(utf8text, textBytes, &bounds); 46 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 47 const SkTextBlobBuilder::RunBuffer& runBuffer = 48 builder->allocRunTextPosH(paint, glyphCount, point.y(), textBytes, SkString(), &bounds); 49 memcpy(runBuffer.utf8text, utf8text, textBytes); 50 const char* txtPtr = utf8text; 51 for (int i = 0; i < glyphCount; ++i) { 52 // Each charater maps to exactly one glyph via SkGlyphCache::unicharToGlyph(). 53 runBuffer.clusters[i] = SkToU32(txtPtr - utf8text); 54 txtPtr += utf8_lead_byte_to_count(txtPtr); 55 SkASSERT(txtPtr <= utf8text + textBytes); 56 } 57 paint.setTextEncoding(SkPaint::kUTF8_TextEncoding); 58 (void)paint.textToGlyphs(utf8text, textBytes, runBuffer.glyphs); 59 (void)paint.getTextWidths(utf8text, textBytes, runBuffer.pos); 60 SkScalar x = point.x(); 61 for (int i = 0; i < glyphCount; ++i) { 62 SkScalar w = runBuffer.pos[i]; 63 runBuffer.pos[i] = x; 64 x += w; 65 } 66 return (SkScalar)x; 67 } 68