blob: aa7fe366c8dd892c7210a3f36bff4fa8deab2416 [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
robertphillipse34f17d2016-07-19 07:59:22 -070051sk_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}
reed@google.com43c27582014-04-08 15:04:29 +000055///////////////////////////////////////////////////////////////////////////////////////////////////
56
reed@google.com43c27582014-04-08 15:04:29 +000057int 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 }
skia.committer@gmail.come1d94432014-04-09 03:04:11 +000062
reed@google.com43c27582014-04-08 15:04:29 +000063 SkASSERT(text);
64
reed@google.com43d6d802014-04-08 16:02:45 +000065 int count = 0; // fix uninitialized warning (even though the switch is complete!)
66
reed@google.com43c27582014-04-08 15:04:29 +000067 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, SkToInt(byteLength >> 1));
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 }
robertphillipse34f17d2016-07-19 07:59:22 -070081 if (!glyphs) {
reed@google.com43c27582014-04-08 15:04:29 +000082 return count;
83 }
84
reed@google.com43c27582014-04-08 15:04:29 +000085 // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding
robertphillipse34f17d2016-07-19 07:59:22 -070086 SkTypeface::Encoding typefaceEncoding;
reed@google.com43c27582014-04-08 15:04:29 +000087 switch (encoding) {
88 case kUTF8_SkTextEncoding:
robertphillipse34f17d2016-07-19 07:59:22 -070089 typefaceEncoding = SkTypeface::kUTF8_Encoding;
reed@google.com43c27582014-04-08 15:04:29 +000090 break;
91 case kUTF16_SkTextEncoding:
robertphillipse34f17d2016-07-19 07:59:22 -070092 typefaceEncoding = SkTypeface::kUTF16_Encoding;
reed@google.com43c27582014-04-08 15:04:29 +000093 break;
94 case kUTF32_SkTextEncoding:
robertphillipse34f17d2016-07-19 07:59:22 -070095 typefaceEncoding = SkTypeface::kUTF32_Encoding;
reed@google.com43c27582014-04-08 15:04:29 +000096 break;
reed@google.com6719d602014-04-08 16:57:05 +000097 default:
98 SkASSERT(kGlyphID_SkTextEncoding == encoding);
reed@google.comefadb4b2014-04-08 15:48:26 +000099 // we can early exit, since we already have glyphIDs
100 memcpy(glyphs, text, count << 1);
101 return count;
reed@google.com43c27582014-04-08 15:04:29 +0000102 }
103
robertphillipse34f17d2016-07-19 07:59:22 -0700104 (void)fTypeface->charsToGlyphs(text, typefaceEncoding, glyphs, count);
reed@google.com43c27582014-04-08 15:04:29 +0000105 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
bungeman13b9c952016-05-12 10:09:30 -0700117sk_sp<SkFont> SkFont::Testing_CreateFromPaint(const SkPaint& paint) {
reed@google.com43c27582014-04-08 15:04:29 +0000118 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
bungeman13b9c952016-05-12 10:09:30 -0700149 return Make(sk_ref_sp(paint.getTypeface()), paint.getTextSize(), paint.getTextScaleX(),
150 paint.getTextSkewX(), maskType, flags);
reed@google.com43c27582014-04-08 15:04:29 +0000151}