Home | History | Annotate | Download | only in core
      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 
     12 static SkTypeface* ref_or_default(SkTypeface* face) {
     13     return face ? SkRef(face) : SkTypeface::RefDefault();
     14 }
     15 
     16 SkFont::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 
     31 SkFont* SkFont::Create(SkTypeface* face, SkScalar size, SkScalar scaleX, SkScalar skewX,
     32                        MaskType mt, uint32_t flags) {
     33     if (size <= 0 || !SkScalarIsFinite(size)) {
     34         return nullptr;
     35     }
     36     if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) {
     37         return nullptr;
     38     }
     39     if (!SkScalarIsFinite(skewX)) {
     40         return nullptr;
     41     }
     42     flags &= kAllFlags;
     43     return new SkFont(face, size, scaleX, skewX, mt, flags);
     44 }
     45 
     46 SkFont* SkFont::Create(SkTypeface* face, SkScalar size, MaskType mt, uint32_t flags) {
     47     return SkFont::Create(face, size, 1, 0, mt, flags);
     48 }
     49 
     50 SkFont* 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 
     57 SkFont::~SkFont() {
     58     SkSafeUnref(fTypeface);
     59 }
     60 
     61 int 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 (nullptr == 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 
    112 SkScalar 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 
    121 SkFont* 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