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 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