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