1a033630e805c407080221e20b236b6054f324670Raph Levien/* 2a033630e805c407080221e20b236b6054f324670Raph Levien * Copyright (C) 2013 The Android Open Source Project 3a033630e805c407080221e20b236b6054f324670Raph Levien * 4a033630e805c407080221e20b236b6054f324670Raph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 5a033630e805c407080221e20b236b6054f324670Raph Levien * you may not use this file except in compliance with the License. 6a033630e805c407080221e20b236b6054f324670Raph Levien * You may obtain a copy of the License at 7a033630e805c407080221e20b236b6054f324670Raph Levien * 8a033630e805c407080221e20b236b6054f324670Raph Levien * http://www.apache.org/licenses/LICENSE-2.0 9a033630e805c407080221e20b236b6054f324670Raph Levien * 10a033630e805c407080221e20b236b6054f324670Raph Levien * Unless required by applicable law or agreed to in writing, software 11a033630e805c407080221e20b236b6054f324670Raph Levien * distributed under the License is distributed on an "AS IS" BASIS, 12a033630e805c407080221e20b236b6054f324670Raph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a033630e805c407080221e20b236b6054f324670Raph Levien * See the License for the specific language governing permissions and 14a033630e805c407080221e20b236b6054f324670Raph Levien * limitations under the License. 15a033630e805c407080221e20b236b6054f324670Raph Levien */ 16a033630e805c407080221e20b236b6054f324670Raph Levien 17a033630e805c407080221e20b236b6054f324670Raph Levien#include <SkTypeface.h> 18a033630e805c407080221e20b236b6054f324670Raph Levien#include <SkPaint.h> 19a033630e805c407080221e20b236b6054f324670Raph Levien 20a033630e805c407080221e20b236b6054f324670Raph Levien#define LOG_TAG "Minikin" 21a033630e805c407080221e20b236b6054f324670Raph Levien#include <cutils/log.h> 22a033630e805c407080221e20b236b6054f324670Raph Levien 23a033630e805c407080221e20b236b6054f324670Raph Levien#include "MinikinSkia.h" 24a033630e805c407080221e20b236b6054f324670Raph Levien 25a033630e805c407080221e20b236b6054f324670Raph Leviennamespace android { 26a033630e805c407080221e20b236b6054f324670Raph Levien 27a033630e805c407080221e20b236b6054f324670Raph LevienMinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) : 28a033630e805c407080221e20b236b6054f324670Raph Levien mTypeface(typeface) { 29a033630e805c407080221e20b236b6054f324670Raph Levien} 30a033630e805c407080221e20b236b6054f324670Raph Levien 31a033630e805c407080221e20b236b6054f324670Raph LevienMinikinFontSkia::~MinikinFontSkia() { 32a033630e805c407080221e20b236b6054f324670Raph Levien SkSafeUnref(mTypeface); 33a033630e805c407080221e20b236b6054f324670Raph Levien} 34a033630e805c407080221e20b236b6054f324670Raph Levien 35a033630e805c407080221e20b236b6054f324670Raph Levienbool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const { 36a033630e805c407080221e20b236b6054f324670Raph Levien SkPaint paint; 37a033630e805c407080221e20b236b6054f324670Raph Levien paint.setTypeface(mTypeface); 38a033630e805c407080221e20b236b6054f324670Raph Levien paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 39a033630e805c407080221e20b236b6054f324670Raph Levien uint16_t glyph16; 40a033630e805c407080221e20b236b6054f324670Raph Levien paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16); 41a033630e805c407080221e20b236b6054f324670Raph Levien *glyph = glyph16; 42531dab6d3a2ffcd13684367659dfd0296f86cfe5Raph Levien return !!glyph16; 43a033630e805c407080221e20b236b6054f324670Raph Levien} 44a033630e805c407080221e20b236b6054f324670Raph Levien 451fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levienstatic void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) { 461a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 471a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien skPaint->setTextSize(paint.size); 48e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien skPaint->setTextScaleX(paint.scaleX); 49e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien skPaint->setTextSkewX(paint.skewX); 50e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags); 511fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien // Apply font fakery on top of user-supplied flags. 521fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery); 531a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 541a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 55a033630e805c407080221e20b236b6054f324670Raph Levienfloat MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id, 56a033630e805c407080221e20b236b6054f324670Raph Levien const MinikinPaint &paint) const { 571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien SkPaint skPaint; 58a033630e805c407080221e20b236b6054f324670Raph Levien uint16_t glyph16 = glyph_id; 59a033630e805c407080221e20b236b6054f324670Raph Levien SkScalar skWidth; 601fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint); 611a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL); 629d9ee3d666c63938311839002ec974673998c6d0Raph Levien#ifdef VERBOSE 631a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth); 649d9ee3d666c63938311839002ec974673998c6d0Raph Levien#endif 651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return skWidth; 661a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien} 671a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 681a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienvoid MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id, 691a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien const MinikinPaint& paint) const { 701a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien SkPaint skPaint; 711a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien uint16_t glyph16 = glyph_id; 72a033630e805c407080221e20b236b6054f324670Raph Levien SkRect skBounds; 731fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint); 741a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds); 751a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien bounds->mLeft = skBounds.fLeft; 761a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien bounds->mTop = skBounds.fTop; 771a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien bounds->mRight = skBounds.fRight; 781a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien bounds->mBottom = skBounds.fBottom; 79a033630e805c407080221e20b236b6054f324670Raph Levien} 80a033630e805c407080221e20b236b6054f324670Raph Levien 81a033630e805c407080221e20b236b6054f324670Raph Levienbool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) { 82a033630e805c407080221e20b236b6054f324670Raph Levien if (buf == NULL) { 83a033630e805c407080221e20b236b6054f324670Raph Levien const size_t tableSize = mTypeface->getTableSize(tag); 84a033630e805c407080221e20b236b6054f324670Raph Levien *size = tableSize; 85a033630e805c407080221e20b236b6054f324670Raph Levien return tableSize != 0; 86a033630e805c407080221e20b236b6054f324670Raph Levien } else { 87a033630e805c407080221e20b236b6054f324670Raph Levien const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf); 88a033630e805c407080221e20b236b6054f324670Raph Levien *size = actualSize; 89a033630e805c407080221e20b236b6054f324670Raph Levien return actualSize != 0; 90a033630e805c407080221e20b236b6054f324670Raph Levien } 91a033630e805c407080221e20b236b6054f324670Raph Levien} 92a033630e805c407080221e20b236b6054f324670Raph Levien 931fc0fa87d42ce9268ece76b85b9edc834593e53aRaph LevienSkTypeface *MinikinFontSkia::GetSkTypeface() const { 94a033630e805c407080221e20b236b6054f324670Raph Levien return mTypeface; 95a033630e805c407080221e20b236b6054f324670Raph Levien} 96a033630e805c407080221e20b236b6054f324670Raph Levien 97a033630e805c407080221e20b236b6054f324670Raph Levienint32_t MinikinFontSkia::GetUniqueId() const { 98a033630e805c407080221e20b236b6054f324670Raph Levien return mTypeface->uniqueID(); 99a033630e805c407080221e20b236b6054f324670Raph Levien} 100a033630e805c407080221e20b236b6054f324670Raph Levien 101e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levienuint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) { 102e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien uint32_t flags = paint->getFlags(); 103e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien SkPaint::Hinting hinting = paint->getHinting(); 104e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien // select only flags that might affect text layout 105e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag | 106e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag | 107e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag | 108e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien SkPaint::kVerticalText_Flag); 109e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien flags |= (hinting << 16); 110e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien return flags; 111e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien} 112e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien 113e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levienvoid MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) { 114e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien paint->setFlags(paintFlags & SkPaint::kAllFlags); 115e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16)); 116e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien} 117e95b5850ac2e56330abf68362451e7614b3dfe16Raph Levien 1181fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levienvoid MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) { 1191fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface()); 1200627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold()); 1210627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien if (fakery.isFakeItalic()) { 1220627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien paint->setTextSkewX(paint->getTextSkewX() - 0.25f); 1230627ec08dcc2e87c17e9b85f045dfb27dc4884b3Raph Levien } 1241fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien} 1251fc0fa87d42ce9268ece76b85b9edc834593e53aRaph Levien 126a033630e805c407080221e20b236b6054f324670Raph Levien} 127