123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- /*
- * Copyright 2019 The Android Open Source Project
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "src/core/SkStrikeSpec.h"
- #include "include/core/SkGraphics.h"
- #include "src/core/SkDraw.h"
- #include "src/core/SkFontPriv.h"
- #include "src/core/SkStrikeCache.h"
- #include "src/core/SkTLazy.h"
- SkStrikeSpec SkStrikeSpec::MakeMask(const SkFont& font, const SkPaint& paint,
- const SkSurfaceProps& surfaceProps,
- SkScalerContextFlags scalerContextFlags,
- const SkMatrix& deviceMatrix) {
- SkStrikeSpec storage;
- storage.commonSetup(font, paint, surfaceProps, scalerContextFlags, deviceMatrix);
- return storage;
- }
- SkStrikeSpec SkStrikeSpec::MakePath(const SkFont& font, const SkPaint& paint,
- const SkSurfaceProps& surfaceProps,
- SkScalerContextFlags scalerContextFlags) {
- SkStrikeSpec storage;
- // setup our std runPaint, in hopes of getting hits in the cache
- SkPaint pathPaint{paint};
- SkFont pathFont{font};
- // The factor to get from the size stored in the strike to the size needed for
- // the source.
- storage.fStrikeToSourceRatio = pathFont.setupForAsPaths(&pathPaint);
- // The sub-pixel position will always happen when transforming to the screen.
- pathFont.setSubpixel(false);
- storage.commonSetup(pathFont, pathPaint, surfaceProps, scalerContextFlags, SkMatrix::I());
- return storage;
- }
- SkStrikeSpec SkStrikeSpec::MakeSourceFallback(
- const SkFont& font,
- const SkPaint& paint,
- const SkSurfaceProps& surfaceProps,
- SkScalerContextFlags scalerContextFlags,
- SkScalar maxSourceGlyphDimension) {
- SkStrikeSpec storage;
- // Subtract 2 to account for the bilerp pad around the glyph
- SkScalar maxAtlasDimension = SkStrikeCommon::kSkSideTooBigForAtlas - 2;
- SkScalar runFontTextSize = font.getSize();
- // Scale the text size down so the long side of all the glyphs will fit in the atlas.
- SkScalar fallbackTextSize = SkScalarFloorToScalar(
- (maxAtlasDimension / maxSourceGlyphDimension) * runFontTextSize);
- SkFont fallbackFont{font};
- fallbackFont.setSize(fallbackTextSize);
- // No sub-pixel needed. The transform to the screen will take care of sub-pixel positioning.
- fallbackFont.setSubpixel(false);
- // The scale factor to go from strike size to the source size for glyphs.
- storage.fStrikeToSourceRatio = runFontTextSize / fallbackTextSize;
- storage.commonSetup(fallbackFont, paint, surfaceProps, scalerContextFlags, SkMatrix::I());
- return storage;
- }
- SkStrikeSpec SkStrikeSpec::MakeCanonicalized(const SkFont& font, const SkPaint* paint) {
- SkStrikeSpec storage;
- SkPaint canonicalizedPaint;
- if (paint != nullptr) {
- canonicalizedPaint = *paint;
- }
- const SkFont* canonicalizedFont = &font;
- SkTLazy<SkFont> pathFont;
- if (ShouldDrawAsPath(canonicalizedPaint, font, SkMatrix::I())) {
- canonicalizedFont = pathFont.set(font);
- storage.fStrikeToSourceRatio = pathFont->setupForAsPaths(nullptr);
- canonicalizedPaint.reset();
- }
- storage.commonSetup(*canonicalizedFont,
- canonicalizedPaint,
- SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType),
- kFakeGammaAndBoostContrast,
- SkMatrix::I());
- return storage;
- }
- SkStrikeSpec SkStrikeSpec::MakeWithNoDevice(const SkFont& font, const SkPaint* paint) {
- SkStrikeSpec storage;
- SkPaint setupPaint;
- if (paint != nullptr) {
- setupPaint = *paint;
- }
- storage.commonSetup(font,
- setupPaint,
- SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType),
- kFakeGammaAndBoostContrast,
- SkMatrix::I());
- return storage;
- }
- SkStrikeSpec SkStrikeSpec::MakeDefault() {
- SkFont defaultFont;
- return MakeCanonicalized(defaultFont);
- }
- bool SkStrikeSpec::ShouldDrawAsPath(
- const SkPaint& paint, const SkFont& font, const SkMatrix& viewMatrix) {
- // hairline glyphs are fast enough so we don't need to cache them
- if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
- return true;
- }
- // we don't cache perspective
- if (viewMatrix.hasPerspective()) {
- return true;
- }
- SkMatrix textMatrix = SkFontPriv::MakeTextMatrix(font);
- textMatrix.postConcat(viewMatrix);
- // we have a self-imposed maximum, just for memory-usage sanity
- SkScalar limit = SkMinScalar(SkGraphics::GetFontCachePointSizeLimit(), 1024);
- SkScalar maxSizeSquared = limit * limit;
- auto distance = [&textMatrix](int XIndex, int YIndex) {
- return textMatrix[XIndex] * textMatrix[XIndex] + textMatrix[YIndex] * textMatrix[YIndex];
- };
- return distance(SkMatrix::kMScaleX, SkMatrix::kMSkewY ) > maxSizeSquared
- || distance(SkMatrix::kMSkewX, SkMatrix::kMScaleY) > maxSizeSquared;
- }
- SkStrikeSpec SkStrikeSpec::MakePDFVector(const SkTypeface& typeface, int* size) {
- SkFont font;
- font.setHinting(SkFontHinting::kNone);
- font.setEdging(SkFont::Edging::kAlias);
- font.setTypeface(sk_ref_sp(&typeface));
- int unitsPerEm = typeface.getUnitsPerEm();
- if (unitsPerEm <= 0) {
- unitsPerEm = 1024;
- }
- if (size) {
- *size = unitsPerEm;
- }
- font.setSize((SkScalar)unitsPerEm);
- SkStrikeSpec storage;
- storage.commonSetup(font,
- SkPaint(),
- SkSurfaceProps(0, kUnknown_SkPixelGeometry),
- kFakeGammaAndBoostContrast,
- SkMatrix::I());
- return storage;
- }
- #if SK_SUPPORT_GPU
- std::tuple<SkStrikeSpec, SkScalar, SkScalar>
- SkStrikeSpec::MakeSDFT(const SkFont& font, const SkPaint& paint,
- const SkSurfaceProps& surfaceProps, const SkMatrix& deviceMatrix,
- const GrTextContext::Options& options) {
- SkStrikeSpec storage;
- SkPaint dfPaint = GrTextContext::InitDistanceFieldPaint(paint);
- SkFont dfFont = GrTextContext::InitDistanceFieldFont(
- font, deviceMatrix, options, &storage.fStrikeToSourceRatio);
- // Fake-gamma and subpixel antialiasing are applied in the shader, so we ignore the
- // passed-in scaler context flags. (It's only used when we fall-back to bitmap text).
- SkScalerContextFlags flags = SkScalerContextFlags::kNone;
- SkScalar minScale, maxScale;
- std::tie(minScale, maxScale) = GrTextContext::InitDistanceFieldMinMaxScale(
- font.getSize(), deviceMatrix, options);
- storage.commonSetup(dfFont, dfPaint, surfaceProps, flags, SkMatrix::I());
- return std::tie(storage, minScale, maxScale);
- }
- sk_sp<GrTextStrike> SkStrikeSpec::findOrCreateGrStrike(GrStrikeCache* cache) const {
- return cache->getStrike(*fAutoDescriptor.getDesc());
- }
- #endif
- void SkStrikeSpec::commonSetup(const SkFont& font, const SkPaint& paint,
- const SkSurfaceProps& surfaceProps,
- SkScalerContextFlags scalerContextFlags,
- const SkMatrix& deviceMatrix) {
- SkScalerContextEffects effects;
- SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
- font, paint, surfaceProps, scalerContextFlags, deviceMatrix,
- &fAutoDescriptor, &effects);
- fMaskFilter = sk_ref_sp(effects.fMaskFilter);
- fPathEffect = sk_ref_sp(effects.fPathEffect);
- fTypeface = font.refTypefaceOrDefault();
- }
- SkScopedStrike SkStrikeSpec::findOrCreateScopedStrike(SkStrikeCacheInterface* cache) const {
- SkScalerContextEffects effects{fPathEffect.get(), fMaskFilter.get()};
- return cache->findOrCreateScopedStrike(*fAutoDescriptor.getDesc(), effects, *fTypeface);
- }
- SkExclusiveStrikePtr SkStrikeSpec::findOrCreateExclusiveStrike(SkStrikeCache* cache) const {
- SkScalerContextEffects effects{fPathEffect.get(), fMaskFilter.get()};
- return cache->findOrCreateStrikeExclusive(*fAutoDescriptor.getDesc(), effects, *fTypeface);
- }
- SkBulkGlyphMetrics::SkBulkGlyphMetrics(const SkStrikeSpec& spec)
- : fStrike{spec.findOrCreateExclusiveStrike()} { }
- SkSpan<const SkGlyph*> SkBulkGlyphMetrics::glyphs(SkSpan<const SkGlyphID> glyphIDs) {
- fGlyphs.reset(glyphIDs.size());
- return fStrike->metrics(glyphIDs, fGlyphs.get());
- }
- SkBulkGlyphMetricsAndPaths::SkBulkGlyphMetricsAndPaths(const SkStrikeSpec& spec)
- : fStrike{spec.findOrCreateExclusiveStrike()} { }
- SkSpan<const SkGlyph*> SkBulkGlyphMetricsAndPaths::glyphs(SkSpan<const SkGlyphID> glyphIDs) {
- fGlyphs.reset(glyphIDs.size());
- return fStrike->preparePaths(glyphIDs, fGlyphs.get());
- }
- SkBulkGlyphMetricsAndImages::SkBulkGlyphMetricsAndImages(const SkStrikeSpec& spec)
- : fStrike{spec.findOrCreateExclusiveStrike()} { }
- SkSpan<const SkGlyph*> SkBulkGlyphMetricsAndImages::glyphs(SkSpan<const SkPackedGlyphID> glyphIDs) {
- fGlyphs.reset(glyphIDs.size());
- return fStrike->prepareImages(glyphIDs, fGlyphs.get());
- }
|