blob: 1300011ec450f29326c2f47d7ea0a1dc64a572be [file] [log] [blame]
reed@google.com43c27582014-04-08 15:04:29 +00001/*
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
bungeman13b9c952016-05-12 10:09:30 -070012SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt,
reed@google.com43c27582014-04-08 15:04:29 +000013 uint32_t flags)
bungeman13b9c952016-05-12 10:09:30 -070014 : fTypeface(face ? std::move(face) : SkTypeface::MakeDefault())
reed@google.com43c27582014-04-08 15:04:29 +000015 , fSize(size)
16 , fScaleX(scaleX)
17 , fSkewX(skewX)
18 , fFlags(flags)
19 , fMaskType(SkToU8(mt))
reed@google.com43c27582014-04-08 15:04:29 +000020{
21 SkASSERT(size > 0);
22 SkASSERT(scaleX > 0);
23 SkASSERT(SkScalarIsFinite(skewX));
24 SkASSERT(0 == (flags & ~kAllFlags));
25}
26
bungeman13b9c952016-05-12 10:09:30 -070027sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX,
28 MaskType mt, uint32_t flags) {
reed@google.com43c27582014-04-08 15:04:29 +000029 if (size <= 0 || !SkScalarIsFinite(size)) {
halcanary96fcdcc2015-08-27 07:41:13 -070030 return nullptr;
reed@google.com43c27582014-04-08 15:04:29 +000031 }
32 if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) {
halcanary96fcdcc2015-08-27 07:41:13 -070033 return nullptr;
reed@google.com43c27582014-04-08 15:04:29 +000034 }
35 if (!SkScalarIsFinite(skewX)) {
halcanary96fcdcc2015-08-27 07:41:13 -070036 return nullptr;
reed@google.com43c27582014-04-08 15:04:29 +000037 }
38 flags &= kAllFlags;
bungeman13b9c952016-05-12 10:09:30 -070039 return sk_sp<SkFont>(new SkFont(std::move(face), size, scaleX, skewX, mt, flags));
reed@google.com43c27582014-04-08 15:04:29 +000040}
41
bungeman13b9c952016-05-12 10:09:30 -070042sk_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);
reed@google.com43c27582014-04-08 15:04:29 +000044}
45
bungeman13b9c952016-05-12 10:09:30 -070046sk_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());
reed@google.com43c27582014-04-08 15:04:29 +000049}
50
51///////////////////////////////////////////////////////////////////////////////////////////////////
52
reed@google.com43c27582014-04-08 15:04:29 +000053int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
54 uint16_t glyphs[], int maxGlyphCount) const {
55 if (0 == byteLength) {
56 return 0;
57 }
skia.committer@gmail.come1d94432014-04-09 03:04:11 +000058
reed@google.com43c27582014-04-08 15:04:29 +000059 SkASSERT(text);
60
reed@google.com43d6d802014-04-08 16:02:45 +000061 int count = 0; // fix uninitialized warning (even though the switch is complete!)
62
reed@google.com43c27582014-04-08 15:04:29 +000063 switch (encoding) {
64 case kUTF8_SkTextEncoding:
65 count = SkUTF8_CountUnichars((const char*)text, byteLength);
66 break;
67 case kUTF16_SkTextEncoding:
68 count = SkUTF16_CountUnichars((const uint16_t*)text, SkToInt(byteLength >> 1));
69 break;
70 case kUTF32_SkTextEncoding:
71 count = SkToInt(byteLength >> 2);
72 break;
73 case kGlyphID_SkTextEncoding:
74 count = SkToInt(byteLength >> 1);
75 break;
76 }
halcanary96fcdcc2015-08-27 07:41:13 -070077 if (nullptr == glyphs) {
reed@google.com43c27582014-04-08 15:04:29 +000078 return count;
79 }
80
reed@google.com43c27582014-04-08 15:04:29 +000081 // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding
82 SkTypeface::Encoding typeface_encoding;
83 switch (encoding) {
84 case kUTF8_SkTextEncoding:
85 typeface_encoding = SkTypeface::kUTF8_Encoding;
86 break;
87 case kUTF16_SkTextEncoding:
88 typeface_encoding = SkTypeface::kUTF16_Encoding;
89 break;
90 case kUTF32_SkTextEncoding:
91 typeface_encoding = SkTypeface::kUTF32_Encoding;
92 break;
reed@google.com6719d602014-04-08 16:57:05 +000093 default:
94 SkASSERT(kGlyphID_SkTextEncoding == encoding);
reed@google.comefadb4b2014-04-08 15:48:26 +000095 // we can early exit, since we already have glyphIDs
96 memcpy(glyphs, text, count << 1);
97 return count;
reed@google.com43c27582014-04-08 15:04:29 +000098 }
99
100 (void)fTypeface->charsToGlyphs(text, typeface_encoding, glyphs, count);
101 return count;
102}
103
104SkScalar SkFont::measureText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
105 // TODO: need access to the cache
106 return -1;
107}
108
109///////////////////////////////////////////////////////////////////////////////////////////////////
110
111#include "SkPaint.h"
112
bungeman13b9c952016-05-12 10:09:30 -0700113sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) {
reed@google.com43c27582014-04-08 15:04:29 +0000114 uint32_t flags = 0;
115 if (paint.isVerticalText()) {
116 flags |= kVertical_Flag;
117 }
118 if (paint.isEmbeddedBitmapText()) {
119 flags |= kEmbeddedBitmaps_Flag;
120 }
121 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
122 flags |= kGenA8FromLCD_Flag;
123 }
124 if (paint.isFakeBoldText()) {
125 flags |= kEmbolden_Flag;
126 }
127
128 if (SkPaint::kFull_Hinting == paint.getHinting()) {
129 flags |= kEnableByteCodeHints_Flag;
130 }
131 if (paint.isAutohinted()) {
132 flags |= kEnableAutoHints_Flag;
133 }
134 if (paint.isSubpixelText() || paint.isLinearText()) {
135 // this is our default
136 } else {
137 flags |= kUseNonlinearMetrics_Flag;
138 }
139
140 MaskType maskType = SkFont::kBW_MaskType;
141 if (paint.isAntiAlias()) {
142 maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType;
143 }
144
bungeman13b9c952016-05-12 10:09:30 -0700145 return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(),
146 paint.getTextSkewX(), maskType, flags);
reed@google.com43c27582014-04-08 15:04:29 +0000147}