blob: 92bf904765dbcc91e25e4e734e67cb70ba62b7f7 [file]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkPaint.h"
#include "SkColorFilter.h"
#include "SkDraw.h"
#include "SkFontDescriptor.h"
#include "SkFontPriv.h"
#include "SkGraphics.h"
#include "SkPaintDefaults.h"
#include "SkPaintPriv.h"
#include "SkPathEffect.h"
#include "SkSafeRange.h"
#include "SkScalar.h"
#include "SkScalerContext.h"
#include "SkShader.h"
#include "SkShaderBase.h"
#include "SkStrike.h"
#include "SkStringUtils.h"
#include "SkTLazy.h"
#include "SkTextBlob.h"
#include "SkTextBlobPriv.h"
#include "SkTextFormatParams.h"
#include "SkTo.h"
#include "SkTypeface.h"
///////////////////////////////////////////////////////////////////////////////
static SkScalar mag2(SkScalar x, SkScalar y) {
return x * x + y * y;
}
static bool tooBig(const SkMatrix& m, SkScalar ma2max) {
return mag2(m[SkMatrix::kMScaleX], m[SkMatrix::kMSkewY]) > ma2max
||
mag2(m[SkMatrix::kMSkewX], m[SkMatrix::kMScaleY]) > ma2max;
}
bool SkFontPriv::TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit) {
SkASSERT(!ctm.hasPerspective());
SkASSERT(!textM.hasPerspective());
SkMatrix matrix;
matrix.setConcat(ctm, textM);
return tooBig(matrix, MaxCacheSize2(maxLimit));
}
SkScalar SkFontPriv::MaxCacheSize2(SkScalar maxLimit) {
// we have a self-imposed maximum, just for memory-usage sanity
const int limit = SkMin32(SkGraphics::GetFontCachePointSizeLimit(), maxLimit);
const SkScalar maxSize = SkIntToScalar(limit);
return maxSize * maxSize;
}
///////////////////////////////////////////////////////////////////////////////
#include "SkUtils.h"
static const SkGlyph& sk_getMetrics_utf8_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharMetrics(SkUTF::NextUTF8(text, stop));
}
static const SkGlyph& sk_getMetrics_utf16_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharMetrics(
SkUTF::NextUTF16((const uint16_t**)text, (const uint16_t*)stop));
}
static const SkGlyph& sk_getMetrics_utf32_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharMetrics(SkUTF::NextUTF32((const int32_t**)text, (const int32_t*)stop));
}
static const SkGlyph& sk_getMetrics_glyph_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
const uint16_t* ptr = *(const uint16_t**)text;
unsigned glyphID = *ptr;
ptr += 1;
*text = (const char*)ptr;
return cache->getGlyphIDMetrics(glyphID);
}
static const SkGlyph& sk_getAdvance_utf8_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharAdvance(SkUTF::NextUTF8(text, stop));
}
static const SkGlyph& sk_getAdvance_utf16_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharAdvance(
SkUTF::NextUTF16((const uint16_t**)text, (const uint16_t*)stop));
}
static const SkGlyph& sk_getAdvance_utf32_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
return cache->getUnicharAdvance(SkUTF::NextUTF32((const int32_t**)text, (const int32_t*)stop));
}
static const SkGlyph& sk_getAdvance_glyph_next(SkStrike* cache,
const char** text,
const char* stop) {
SkASSERT(cache != nullptr);
SkASSERT(text != nullptr);
const uint16_t* ptr = *(const uint16_t**)text;
unsigned glyphID = *ptr;
ptr += 1;
*text = (const char*)ptr;
return cache->getGlyphIDAdvance(glyphID);
}
SkFontPriv::GlyphCacheProc SkFontPriv::GetGlyphCacheProc(SkTextEncoding encoding,
bool needFullMetrics) {
static const GlyphCacheProc gGlyphCacheProcs[] = {
sk_getMetrics_utf8_next,
sk_getMetrics_utf16_next,
sk_getMetrics_utf32_next,
sk_getMetrics_glyph_next,
sk_getAdvance_utf8_next,
sk_getAdvance_utf16_next,
sk_getAdvance_utf32_next,
sk_getAdvance_glyph_next,
};
unsigned index = static_cast<unsigned>(encoding);
if (!needFullMetrics) {
index += 4;
}
SkASSERT(index < SK_ARRAY_COUNT(gGlyphCacheProcs));
return gGlyphCacheProcs[index];
}
///////////////////////////////////////////////////////////////////////////////
// return true if the paint is just a single color (i.e. not a shader). If its
// a shader, then we can't compute a const luminance for it :(
static bool just_a_color(const SkPaint& paint, SkColor* color) {
SkColor c = paint.getColor();
const auto* shader = as_SB(paint.getShader());
if (shader && !shader->asLuminanceColor(&c)) {
return false;
}
if (paint.getColorFilter()) {
c = paint.getColorFilter()->filterColor(c);
}
if (color) {
*color = c;
}
return true;
}
SkColor SkPaint::computeLuminanceColor() const {
SkColor c;
if (!just_a_color(*this, &c)) {
c = SkColorSetRGB(0x7F, 0x80, 0x7F);
}
return c;
}