1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <SkTypeface.h> 18 #include <SkPaint.h> 19 20 #define LOG_TAG "Minikin" 21 #include <cutils/log.h> 22 23 #include "MinikinSkia.h" 24 25 namespace android { 26 27 MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) : 28 mTypeface(typeface) { 29 } 30 31 MinikinFontSkia::~MinikinFontSkia() { 32 SkSafeUnref(mTypeface); 33 } 34 35 bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const { 36 SkPaint paint; 37 paint.setTypeface(mTypeface); 38 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding); 39 uint16_t glyph16; 40 paint.textToGlyphs(&codepoint, sizeof(codepoint), &glyph16); 41 *glyph = glyph16; 42 return !!glyph16; 43 } 44 45 static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) { 46 skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 47 skPaint->setTextSize(paint.size); 48 skPaint->setTextScaleX(paint.scaleX); 49 skPaint->setTextSkewX(paint.skewX); 50 MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags); 51 // Apply font fakery on top of user-supplied flags. 52 MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery); 53 } 54 55 float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id, 56 const MinikinPaint &paint) const { 57 SkPaint skPaint; 58 uint16_t glyph16 = glyph_id; 59 SkScalar skWidth; 60 MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint); 61 skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL); 62 #ifdef VERBOSE 63 ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth); 64 #endif 65 return skWidth; 66 } 67 68 void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id, 69 const MinikinPaint& paint) const { 70 SkPaint skPaint; 71 uint16_t glyph16 = glyph_id; 72 SkRect skBounds; 73 MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint); 74 skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds); 75 bounds->mLeft = skBounds.fLeft; 76 bounds->mTop = skBounds.fTop; 77 bounds->mRight = skBounds.fRight; 78 bounds->mBottom = skBounds.fBottom; 79 } 80 81 bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) { 82 if (buf == NULL) { 83 const size_t tableSize = mTypeface->getTableSize(tag); 84 *size = tableSize; 85 return tableSize != 0; 86 } else { 87 const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf); 88 *size = actualSize; 89 return actualSize != 0; 90 } 91 } 92 93 SkTypeface *MinikinFontSkia::GetSkTypeface() const { 94 return mTypeface; 95 } 96 97 int32_t MinikinFontSkia::GetUniqueId() const { 98 return mTypeface->uniqueID(); 99 } 100 101 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) { 102 uint32_t flags = paint->getFlags(); 103 SkPaint::Hinting hinting = paint->getHinting(); 104 // select only flags that might affect text layout 105 flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag | 106 SkPaint::kSubpixelText_Flag | SkPaint::kDevKernText_Flag | 107 SkPaint::kEmbeddedBitmapText_Flag | SkPaint::kAutoHinting_Flag | 108 SkPaint::kVerticalText_Flag); 109 flags |= (hinting << 16); 110 return flags; 111 } 112 113 void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) { 114 paint->setFlags(paintFlags & SkPaint::kAllFlags); 115 paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16)); 116 } 117 118 void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) { 119 paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface()); 120 paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold()); 121 if (fakery.isFakeItalic()) { 122 paint->setTextSkewX(paint->getTextSkewX() - 0.25f); 123 } 124 } 125 126 } 127