WIP -- SkFont

BUG=skia:
R=bungeman@google.com, fmalita@chromium.org

Review URL: https://codereview.chromium.org/185293018

git-svn-id: http://skia.googlecode.com/svn/trunk@14090 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkFont.cpp b/src/core/SkFont.cpp
new file mode 100644
index 0000000..2c16186
--- /dev/null
+++ b/src/core/SkFont.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFont.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
+static SkTypeface* ref_or_default(SkTypeface* face) {
+    return face ? SkRef(face) : SkTypeface::RefDefault();
+}
+
+SkFont::SkFont(SkTypeface* face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt,
+               uint32_t flags)
+    : fTypeface(ref_or_default(face))
+    , fSize(size)
+    , fScaleX(scaleX)
+    , fSkewX(skewX)
+    , fFlags(flags)
+    , fMaskType(SkToU8(mt))
+    , fPad(0)
+{
+    SkASSERT(size > 0);
+    SkASSERT(scaleX > 0);
+    SkASSERT(SkScalarIsFinite(skewX));
+    SkASSERT(0 == (flags & ~kAllFlags));
+}
+
+SkFont* SkFont::Create(SkTypeface* face, SkScalar size, SkScalar scaleX, SkScalar skewX,
+                       MaskType mt, uint32_t flags) {
+    if (size <= 0 || !SkScalarIsFinite(size)) {
+        return NULL;
+    }
+    if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) {
+        return NULL;
+    }
+    if (!SkScalarIsFinite(skewX)) {
+        return NULL;
+    }
+    flags &= kAllFlags;
+    return SkNEW_ARGS(SkFont, (face, size, scaleX, skewX, mt, flags));
+}
+
+SkFont* SkFont::Create(SkTypeface* face, SkScalar size, MaskType mt, uint32_t flags) {
+    return SkFont::Create(face, size, 1, 0, mt, flags);
+}
+
+SkFont* SkFont::cloneWithSize(SkScalar newSize) const {
+    return SkFont::Create(this->getTypeface(), newSize, this->getScaleX(), this->getSkewX(),
+                          this->getMaskType(), this->getFlags());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+SkFont::~SkFont() {
+    SkSafeUnref(fTypeface);
+}
+
+int SkFont::textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
+                         uint16_t glyphs[], int maxGlyphCount) const {
+    if (0 == byteLength) {
+        return 0;
+    }
+    
+    SkASSERT(text);
+
+    int count;
+    switch (encoding) {
+        case kUTF8_SkTextEncoding:
+            count = SkUTF8_CountUnichars((const char*)text, byteLength);
+            break;
+        case kUTF16_SkTextEncoding:
+            count = SkUTF16_CountUnichars((const uint16_t*)text, SkToInt(byteLength >> 1));
+            break;
+        case kUTF32_SkTextEncoding:
+            count = SkToInt(byteLength >> 2);
+            break;
+        case kGlyphID_SkTextEncoding:
+            count = SkToInt(byteLength >> 1);
+            break;
+    }
+    if (NULL == glyphs) {
+        return count;
+    }
+
+    if (kGlyphID_SkTextEncoding == encoding) {
+        memcpy(glyphs, text, count << 1);
+        return count;
+    }
+
+    // TODO: unify/eliminate SkTypeface::Encoding with SkTextEncoding
+    SkTypeface::Encoding typeface_encoding;
+    switch (encoding) {
+        case kUTF8_SkTextEncoding:
+            typeface_encoding = SkTypeface::kUTF8_Encoding;
+            break;
+        case kUTF16_SkTextEncoding:
+            typeface_encoding = SkTypeface::kUTF16_Encoding;
+            break;
+        case kUTF32_SkTextEncoding:
+            typeface_encoding = SkTypeface::kUTF32_Encoding;
+            break;
+        case kGlyphID_SkTextEncoding:
+            SkASSERT(0);    // can't get here
+    }
+
+    (void)fTypeface->charsToGlyphs(text, typeface_encoding, glyphs, count);
+    return count;
+}
+
+SkScalar SkFont::measureText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
+    // TODO: need access to the cache
+    return -1;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "SkPaint.h"
+
+SkFont* SkFont::Testing_CreateFromPaint(const SkPaint& paint) {
+    uint32_t flags = 0;
+    if (paint.isVerticalText()) {
+        flags |= kVertical_Flag;
+    }
+    if (paint.isEmbeddedBitmapText()) {
+        flags |= kEmbeddedBitmaps_Flag;
+    }
+    if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
+        flags |= kGenA8FromLCD_Flag;
+    }
+    if (paint.isFakeBoldText()) {
+        flags |= kEmbolden_Flag;
+    }
+
+    if (SkPaint::kFull_Hinting == paint.getHinting()) {
+        flags |= kEnableByteCodeHints_Flag;
+    }
+    if (paint.isAutohinted()) {
+        flags |= kEnableAutoHints_Flag;
+    }
+    if (paint.isSubpixelText() || paint.isLinearText()) {
+        // this is our default
+    } else {
+        flags |= kUseNonlinearMetrics_Flag;
+    }
+
+    MaskType maskType = SkFont::kBW_MaskType;
+    if (paint.isAntiAlias()) {
+        maskType = paint.isLCDRenderText() ? kLCD_MaskType : kA8_MaskType;
+    }
+
+    return Create(paint.getTypeface(),
+                  paint.getTextSize(), paint.getTextScaleX(), paint.getTextSkewX(),
+                  maskType, flags);
+}