1/* 2 * Copyright 2014 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 8#include "SkFont.h" 9#include "SkTypeface.h" 10#include "SkUtils.h" 11 12SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt, 13 uint32_t flags) 14 : fTypeface(face ? std::move(face) : SkTypeface::MakeDefault()) 15 , fSize(size) 16 , fScaleX(scaleX) 17 , fSkewX(skewX) 18 , fFlags(flags) 19 , fMaskType(SkToU8(mt)) 20{ 21 SkASSERT(size > 0); 22 SkASSERT(scaleX > 0); 23 SkASSERT(SkScalarIsFinite(skewX)); 24 SkASSERT(0 == (flags & ~kAllFlags)); 25} 26 27sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, 28 MaskType mt, uint32_t flags) { 29 if (size <= 0 || !SkScalarIsFinite(size)) { 30 return nullptr; 31 } 32 if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) { 33 return nullptr; 34 } 35 if (!SkScalarIsFinite(skewX)) { 36 return nullptr; 37 } 38 flags &= kAllFlags; 39 return sk_sp<SkFont>(new SkFont(std::move(face), size, scaleX, skewX, mt, flags)); 40} 41 42sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, MaskType mt, uint32_t flags) { 43 return SkFont::Make(std::move(face), size, 1, 0, mt, flags); 44} 45 46sk_sp<SkFont> SkFont::makeWithSize(SkScalar newSize) const { 47 return SkFont::Make(sk_ref_sp(this->getTypeface()), newSize, this->getScaleX(), 48 this->getSkewX(), this->getMaskType(), this->getFlags()); 49} 50 51sk_sp<SkFont> SkFont::makeWithFlags(uint32_t newFlags) const { 52 return SkFont::Make(sk_ref_sp(this->getTypeface()), this->getSize(), this->getScaleX(), 53 this->getSkewX(), this->getMaskType(), newFlags); 54} 55/////////////////////////////////////////////////////////////////////////////////////////////////// 56 57int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding, 58 uint16_t glyphs[], int maxGlyphCount) const { 59 if (0 == byteLength) { 60 return 0; 61 } 62 63 SkASSERT(text); 64 65 int count = 0; // fix uninitialized warning (even though the switch is complete!) 66 67 switch (encoding) { 68 case kUTF8_SkTextEncoding: 69 count = SkUTF8_CountUnichars((const char*)text, byteLength); 70 break; 71 case kUTF16_SkTextEncoding: 72 count = SkUTF16_CountUnichars((const uint16_t*)text, byteLength); 73 break; 74 case kUTF32_SkTextEncoding: 75 count = SkToInt(byteLength >> 2); 76 break; 77 case kGlyphID_SkTextEncoding: 78 count = SkToInt(byteLength >> 1); 79 break; 80 } 81 if (!glyphs) { 82 return count; 83 } 84 85 // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding 86 SkTypeface::Encoding typefaceEncoding; 87 switch (encoding) { 88 case kUTF8_SkTextEncoding: 89 typefaceEncoding = SkTypeface::kUTF8_Encoding; 90 break; 91 case kUTF16_SkTextEncoding: 92 typefaceEncoding = SkTypeface::kUTF16_Encoding; 93 break; 94 case kUTF32_SkTextEncoding: 95 typefaceEncoding = SkTypeface::kUTF32_Encoding; 96 break; 97 default: 98 SkASSERT(kGlyphID_SkTextEncoding == encoding); 99 // we can early exit, since we already have glyphIDs 100 memcpy(glyphs, text, count << 1); 101 return count; 102 } 103 104 (void)fTypeface->charsToGlyphs(text, typefaceEncoding, glyphs, count); 105 return count; 106} 107 108SkScalar SkFont::measureText(const void* text, size_t byteLength, SkTextEncoding encoding) const { 109 // TODO: need access to the cache 110 return -1; 111} 112 113/////////////////////////////////////////////////////////////////////////////////////////////////// 114 115#include "SkPaint.h" 116 117sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) { 118 uint32_t flags = 0; 119 if (paint.isVerticalText()) { 120 flags |= kVertical_Flag; 121 } 122 if (paint.isEmbeddedBitmapText()) { 123 flags |= kEmbeddedBitmaps_Flag; 124 } 125 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) { 126 flags |= kGenA8FromLCD_Flag; 127 } 128 if (paint.isFakeBoldText()) { 129 flags |= kEmbolden_Flag; 130 } 131 132 if (SkPaint::kFull_Hinting == paint.getHinting()) { 133 flags |= kEnableByteCodeHints_Flag; 134 } 135 if (paint.isAutohinted()) { 136 flags |= kEnableAutoHints_Flag; 137 } 138 if (paint.isSubpixelText() || paint.isLinearText()) { 139 // this is our default 140 } else { 141 flags |= kUseNonlinearMetrics_Flag; 142 } 143 144 MaskType maskType = SkFont::kBW_MaskType; 145 if (paint.isAntiAlias()) { 146 maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType; 147 } 148 149 return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(), 150 paint.getTextSkewX(), maskType, flags); 151} 152