|  | /* | 
|  | * 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 "include/core/SkTypeface.h" | 
|  | #include "include/private/base/SkTo.h" | 
|  | #include "src/core/SkFontPriv.h" | 
|  | #include "src/core/SkReadBuffer.h" | 
|  | #include "src/core/SkWriteBuffer.h" | 
|  |  | 
|  | // packed int at the beginning of the serialized font: | 
|  | // | 
|  | //  control_bits:8 size_as_byte:8 flags:12 edging:2 hinting:2 | 
|  |  | 
|  | enum { | 
|  | kSize_Is_Byte_Bit   = 1 << 31, | 
|  | kHas_ScaleX_Bit     = 1 << 30, | 
|  | kHas_SkewX_Bit      = 1 << 29, | 
|  | kHas_Typeface_Bit   = 1 << 28, | 
|  |  | 
|  | kShift_for_Size     = 16, | 
|  | kMask_For_Size      = 0xFF, | 
|  |  | 
|  | kShift_For_Flags    = 4, | 
|  | kMask_For_Flags     = 0xFFF, | 
|  |  | 
|  | kShift_For_Edging   = 2, | 
|  | kMask_For_Edging    = 0x3, | 
|  |  | 
|  | kShift_For_Hinting  = 0, | 
|  | kMask_For_Hinting   = 0x3 | 
|  | }; | 
|  |  | 
|  | static bool scalar_is_byte(SkScalar x) { | 
|  | int ix = (int)x; | 
|  | return ix == x && ix >= 0 && ix <= kMask_For_Size; | 
|  | } | 
|  |  | 
|  | void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) { | 
|  | SkASSERT(font.fFlags <= SkFont::kAllFlags); | 
|  | SkASSERT((font.fFlags & ~kMask_For_Flags) == 0); | 
|  | SkASSERT((font.fEdging & ~kMask_For_Edging) == 0); | 
|  | SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0); | 
|  |  | 
|  | uint32_t packed = 0; | 
|  | packed |= font.fFlags << kShift_For_Flags; | 
|  | packed |= font.fEdging << kShift_For_Edging; | 
|  | packed |= font.fHinting << kShift_For_Hinting; | 
|  |  | 
|  | if (scalar_is_byte(font.fSize)) { | 
|  | packed |= kSize_Is_Byte_Bit; | 
|  | packed |= (int)font.fSize << kShift_for_Size; | 
|  | } | 
|  | if (font.fScaleX != 1) { | 
|  | packed |= kHas_ScaleX_Bit; | 
|  | } | 
|  | if (font.fSkewX != 0) { | 
|  | packed |= kHas_SkewX_Bit; | 
|  | } | 
|  | if (font.fTypeface) { | 
|  | packed |= kHas_Typeface_Bit; | 
|  | } | 
|  |  | 
|  | buffer.write32(packed); | 
|  | if (!(packed & kSize_Is_Byte_Bit)) { | 
|  | buffer.writeScalar(font.fSize); | 
|  | } | 
|  | if (packed & kHas_ScaleX_Bit) { | 
|  | buffer.writeScalar(font.fScaleX); | 
|  | } | 
|  | if (packed & kHas_SkewX_Bit) { | 
|  | buffer.writeScalar(font.fSkewX); | 
|  | } | 
|  | if (packed & kHas_Typeface_Bit) { | 
|  | buffer.writeTypeface(font.fTypeface.get()); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool SkFontPriv::Unflatten(SkFont* font, SkReadBuffer& buffer) { | 
|  | const uint32_t packed = buffer.read32(); | 
|  |  | 
|  | if (packed & kSize_Is_Byte_Bit) { | 
|  | font->fSize = (packed >> kShift_for_Size) & kMask_For_Size; | 
|  | } else { | 
|  | font->fSize = buffer.readScalar(); | 
|  | } | 
|  | if (packed & kHas_ScaleX_Bit) { | 
|  | font->fScaleX = buffer.readScalar(); | 
|  | } | 
|  | if (packed & kHas_SkewX_Bit) { | 
|  | font->fSkewX = buffer.readScalar(); | 
|  | } | 
|  | if (packed & kHas_Typeface_Bit) { | 
|  | font->fTypeface = buffer.readTypeface(); | 
|  | } | 
|  |  | 
|  | SkASSERT(SkFont::kAllFlags <= kMask_For_Flags); | 
|  | // we & with kAllFlags, to clear out any unknown flag bits | 
|  | font->fFlags = SkToU8((packed >> kShift_For_Flags) & SkFont::kAllFlags); | 
|  |  | 
|  | unsigned edging = (packed >> kShift_For_Edging) & kMask_For_Edging; | 
|  | if (edging > (unsigned)SkFont::Edging::kSubpixelAntiAlias) { | 
|  | edging = 0; | 
|  | } | 
|  | font->fEdging = SkToU8(edging); | 
|  |  | 
|  | unsigned hinting = (packed >> kShift_For_Hinting) & kMask_For_Hinting; | 
|  | if (hinting > (unsigned)SkFontHinting::kFull) { | 
|  | hinting = 0; | 
|  | } | 
|  | font->fHinting = SkToU8(hinting); | 
|  |  | 
|  | return buffer.isValid(); | 
|  | } |