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