/*
* 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))
{
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 = 0; // fix uninitialized warning (even though the switch is complete!)
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;
}
// 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;
default:
SkASSERT(kGlyphID_SkTextEncoding == encoding);
// we can early exit, since we already have glyphIDs
memcpy(glyphs, text, count << 1);
return count;
}
(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);
}