/* To enable additional blitters (and fontscaler code) to support separate
alpha channels for R G B channels, define SK_SUPPORT_LCDTEXT
*/
-#define SK_SUPPORT_LCDTEXT
+//#define SK_SUPPORT_LCDTEXT
/* If SK_DEBUG is defined, then you can optionally define SK_SUPPORT_UNITTEST
which will run additional self-tests at startup. These can take a long time,
///////////////////////////////////////////////////////////////////////////
+ /** Given a filled-out rec, the fonthost may decide to modify it to reflect
+ what the host is actually capable of fulfilling. For example, if the
+ rec is requesting a level of hinting that, for this host, maps some
+ other level (e.g. kFull -> kNormal), it should update the rec to reflect
+ what will actually be done. This is an optimization so that the font
+ cache does not contain different recs (i.e. keys) that in reality map to
+ the same output.
+
+ A lazy (but valid) fonthost can do nothing in its FilterRec routine.
+ */
+ static void FilterRec(SkScalerContext::Rec* rec);
+
+ ///////////////////////////////////////////////////////////////////////////
+
/** Return the number of tables in the font
*/
static int CountTables(SkFontID);
kJustRenderImage_CreateMode, //!< render into preallocate mask
kComputeBoundsAndRenderImage_CreateMode //!< compute bounds, alloc image and render into it
};
+
+ static bool FormatIsLCD(Format fm) {
+ return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm;
+ }
};
#endif
kGammaForWhite_Flag = 0x08, // illegal to set both Gamma flags
// together, these two flags resulting in a two bit value which matches
// up with the SkPaint::Hinting enum.
- kHintingBit1 = 0x10,
- kHintingBit2 = 0x20,
+ kHintingBit1_Flag = 0x10,
+ kHintingBit2_Flag = 0x20,
};
struct Rec {
uint32_t fFontID;
}
void setHinting(SkPaint::Hinting hinting) {
- fFlags = (fFlags & ~(kHintingBit1 | kHintingBit2)) |
+ fFlags = (fFlags & ~(kHintingBit1_Flag | kHintingBit2_Flag)) |
(static_cast<int>(hinting) << 4);
}
+
+ SkMask::Format getFormat() const {
+ return static_cast<SkMask::Format>(fMaskFormat);
+ }
+
+ bool isLCD() const {
+ return SkMask::FormatIsLCD(this->getFormat());
+ }
};
SkScalerContext(const SkDescriptor* desc);
return SkMask::kBW_Format;
}
-void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec)
+void SkScalerContext::MakeRec(const SkPaint& paint,
+ const SkMatrix* deviceMatrix, Rec* rec)
{
- SkASSERT(deviceMatrix == NULL || (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
+ SkASSERT(deviceMatrix == NULL ||
+ (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
rec->fTextSize = paint.getTextSize();
rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
rec->fFlags = SkToU8(flags);
rec->setHinting(paint.getHinting());
+
+ /* Allow the fonthost to modify our rec before we use it as a key into the
+ cache. This way if we're asking for something that they will ignore,
+ they can modify our rec up front, so we don't create duplicate cache
+ entries.
+ */
+ SkFontHost::FilterRec(rec);
}
#define MIN_SIZE_FOR_EFFECT_BUFFER 1024
///////////////////////////////////////////////////////////////////////////
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+ // collapse full->normaling hinting if we're not doing LCD
+ SkPaint::Hinting h = rec->getHinting();
+ if (SkPaint::kFull_Hinting == h && !rec->isLCD()) {
+ rec->setHinting(SkPaint::kNormal_Hinting);
+ }
+}
+
SkScalerContext_FreeType::SkScalerContext_FreeType(const SkDescriptor* desc)
: SkScalerContext(desc) {
SkAutoMutexAcquire ac(gFTMutex);
static OSStatus Close(void *cb);
};
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+ // we only support 2 levels of hinting
+ SkPaint::Hinting h = rec->getHinting();
+ if (SkPaint::kSlight_Hinting == h) {
+ h = SkPaint::kNo_Hinting;
+ } else if (SkPaint::kFull_Hinting == h) {
+ h = SkPaint::kNormal_Hinting;
+ }
+ rec->setHinting(h);
+
+ // we don't support LCD text
+ if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
+ rec->fMaskFormat = SkMask::kA8_Format;
+ }
+}
+
SkScalerContext_Mac::SkScalerContext_Mac(const SkDescriptor* desc)
: SkScalerContext(desc), fLayout(0), fStyle(0)
{