/*
* Copyright 2010 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGlyph_DEFINED
#define GrGlyph_DEFINED
#include "GrDrawOpAtlas.h"
#include "GrRect.h"
#include "GrTypes.h"
#include "SkChecksum.h"
#include "SkFixed.h"
#include "SkPath.h"
struct GrGlyph {
enum MaskStyle {
kCoverage_MaskStyle,
kDistance_MaskStyle
};
static GrMaskFormat FormatFromSkGlyph(const SkGlyph& glyph) {
SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
switch (format) {
case SkMask::kBW_Format:
case SkMask::kSDF_Format:
// fall through to kA8 -- we store BW and SDF glyphs in our 8-bit cache
case SkMask::kA8_Format:
return kA8_GrMaskFormat;
case SkMask::k3D_Format:
return kA8_GrMaskFormat; // ignore the mul and add planes, just use the mask
case SkMask::kLCD16_Format:
return kA565_GrMaskFormat;
case SkMask::kARGB32_Format:
return kARGB_GrMaskFormat;
default:
SkDEBUGFAIL("unsupported SkMask::Format");
return kA8_GrMaskFormat;
}
}
static GrIRect16 BoundsFromSkGlyph(const SkGlyph& glyph) {
return GrIRect16::MakeXYWH(glyph.fLeft,
glyph.fTop,
glyph.fWidth,
glyph.fHeight);
}
static MaskStyle MaskStyleFromSkGlyph(const SkGlyph& skGlyph) {
return (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format
? GrGlyph::MaskStyle::kDistance_MaskStyle
: GrGlyph::MaskStyle::kCoverage_MaskStyle;
}
GrGlyph(const SkGlyph& skGlyph)
: fPackedID{skGlyph.getPackedID()}
, fMaskFormat{FormatFromSkGlyph(skGlyph)}
, fMaskStyle{MaskStyleFromSkGlyph(skGlyph)}
, fBounds{BoundsFromSkGlyph(skGlyph)} {}
SkRect destRect(SkPoint origin) {
return SkRect::MakeXYWH(
SkIntToScalar(fBounds.fLeft) + origin.x(),
SkIntToScalar(fBounds.fTop) + origin.y(),
SkIntToScalar(fBounds.width()),
SkIntToScalar(fBounds.height()));
}
SkRect destRect(SkPoint origin, SkScalar textScale) {
if (fMaskStyle == kCoverage_MaskStyle) {
return SkRect::MakeXYWH(
SkIntToScalar(fBounds.fLeft) * textScale + origin.x(),
SkIntToScalar(fBounds.fTop) * textScale + origin.y(),
SkIntToScalar(fBounds.width()) * textScale,
SkIntToScalar(fBounds.height()) * textScale);
} else {
return SkRect::MakeXYWH(
(SkIntToScalar(fBounds.fLeft) + SK_DistanceFieldInset) * textScale + origin.x(),
(SkIntToScalar(fBounds.fTop) + SK_DistanceFieldInset) * textScale + origin.y(),
(SkIntToScalar(fBounds.width()) - 2 * SK_DistanceFieldInset) * textScale,
(SkIntToScalar(fBounds.height()) - 2 * SK_DistanceFieldInset) * textScale);
}
}
int width() const { return fBounds.width(); }
int height() const { return fBounds.height(); }
uint32_t pageIndex() const { return GrDrawOpAtlas::GetPageIndexFromID(fID); }
MaskStyle maskStyle() const { return fMaskStyle; }
// GetKey and Hash for the the hash table.
static const SkPackedGlyphID& GetKey(const GrGlyph& glyph) {
return glyph.fPackedID;
}
static uint32_t Hash(SkPackedGlyphID key) {
return SkChecksum::Mix(key.hash());
}
const SkPackedGlyphID fPackedID;
const GrMaskFormat fMaskFormat;
const MaskStyle fMaskStyle;
const GrIRect16 fBounds;
SkIPoint16 fAtlasLocation{0, 0};
GrDrawOpAtlas::AtlasID fID{GrDrawOpAtlas::kInvalidAtlasID};
};
#endif