1 /* 2 * Copyright 2023 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkTypeface_Fontations_priv_DEFINED 9 #define SkTypeface_Fontations_priv_DEFINED 10 11 #include "include/core/SkFontParameters.h" 12 #include "include/core/SkPath.h" 13 #include "include/core/SkSpan.h" 14 #include "include/core/SkStream.h" 15 #include "include/core/SkTypeface.h" 16 #include "include/private/base/SkOnce.h" 17 #include "include/private/base/SkTArray.h" 18 #include "src/core/SkAdvancedTypefaceMetrics.h" 19 #include "src/core/SkScalerContext.h" 20 #include "src/ports/fontations/src/ffi.rs.h" 21 22 #include <memory> 23 24 class SkStreamAsset; 25 class SkFontationsScalerContext; 26 27 namespace sk_fontations { 28 29 /** Implementation of AxisWrapper FFI C++ interface, allowing Rust to call back into 30 * C++ for populating variable axis availability information, see skpath_bridge.h. */ 31 class AxisWrapper : public fontations_ffi::AxisWrapper { 32 public: 33 AxisWrapper(SkFontParameters::Variation::Axis axisArray[], size_t axisCount); 34 AxisWrapper() = delete; 35 /* From fontations_ffi::AxisWrapper. */ 36 bool populate_axis( 37 size_t i, uint32_t axisTag, float min, float def, float max, bool hidden) override; 38 size_t size() const override; 39 40 private: 41 SkFontParameters::Variation::Axis* fAxisArray; 42 size_t fAxisCount; 43 }; 44 45 class ColorPainter : public fontations_ffi::ColorPainterWrapper { 46 public: 47 ColorPainter() = delete; 48 ColorPainter(SkFontationsScalerContext& scaler_context, 49 SkCanvas& canvas, 50 SkSpan<const SkColor> palette, 51 SkColor foregroundColor, 52 bool antialias, 53 uint16_t upem); 54 55 // fontations_ffi::ColorPainter interface. is_bounds_mode()56 virtual bool is_bounds_mode() override { return false; } 57 virtual void push_transform(const fontations_ffi::Transform& transform) override; 58 virtual void pop_transform() override; 59 virtual void push_clip_glyph(uint16_t glyph_id) override; 60 virtual void push_clip_rectangle(float x_min, float y_min, float x_max, float y_max) override; 61 virtual void pop_clip() override; 62 63 // Paint*Gradient equivalents: 64 virtual void fill_solid(uint16_t palette_index, float alpha) override; 65 virtual void fill_radial(const fontations_ffi::FillRadialParams& fill_radial_params, 66 fontations_ffi::BridgeColorStops&, 67 uint8_t extend_mode) override; 68 virtual void fill_linear(const fontations_ffi::FillLinearParams& fill_linear_params, 69 fontations_ffi::BridgeColorStops&, 70 uint8_t extend_mode) override; 71 virtual void fill_sweep(const fontations_ffi::FillSweepParams& fill_sweep_params, 72 fontations_ffi::BridgeColorStops&, 73 uint8_t extend_mode) override; 74 75 // Optimized calls that allow a SkCanvas::drawPath() call. 76 virtual void fill_glyph_solid(uint16_t glyph_id, uint16_t palette_index, float alpha) override; 77 virtual void fill_glyph_radial(uint16_t glyph_id, 78 const fontations_ffi::Transform& transform, 79 const fontations_ffi::FillRadialParams& fill_radial_params, 80 fontations_ffi::BridgeColorStops& stops, 81 uint8_t) override; 82 virtual void fill_glyph_linear(uint16_t glyph_id, 83 const fontations_ffi::Transform& transform, 84 const fontations_ffi::FillLinearParams& fill_linear_params, 85 fontations_ffi::BridgeColorStops& stops, 86 uint8_t) override; 87 virtual void fill_glyph_sweep(uint16_t glyph_id, 88 const fontations_ffi::Transform& transform, 89 const fontations_ffi::FillSweepParams& fill_sweep_params, 90 fontations_ffi::BridgeColorStops& stops, 91 uint8_t) override; 92 93 // compositeMode arg matches composite mode values from the OpenType COLR table spec. 94 virtual void push_layer(uint8_t compositeMode) override; 95 virtual void pop_layer() override; 96 97 private: 98 void configure_solid_paint(uint16_t palette_index, float alpha, SkPaint& paint); 99 void configure_linear_paint(const fontations_ffi::FillLinearParams& fill_linear_params, 100 fontations_ffi::BridgeColorStops& bridge_stops, 101 uint8_t extend_mode, 102 SkPaint& paint, 103 SkMatrix* = nullptr); 104 void configure_radial_paint(const fontations_ffi::FillRadialParams& fill_radial_params, 105 fontations_ffi::BridgeColorStops& bridge_stops, 106 uint8_t extend_mode, 107 SkPaint& paint, 108 SkMatrix* = nullptr); 109 void configure_sweep_paint(const fontations_ffi::FillSweepParams& sweep_params, 110 fontations_ffi::BridgeColorStops& bridge_stops, 111 uint8_t extend_mode, 112 SkPaint& paint, 113 SkMatrix* = nullptr); 114 SkFontationsScalerContext& fScalerContext; 115 SkCanvas& fCanvas; 116 SkSpan<const SkColor> fPalette; 117 SkColor fForegroundColor; 118 bool fAntialias; 119 uint16_t fUpem; 120 }; 121 122 /** Tracks transforms and clips to compute a bounding box without drawing pixels. */ 123 class BoundsPainter : public fontations_ffi::ColorPainterWrapper { 124 public: 125 BoundsPainter() = delete; 126 BoundsPainter(SkFontationsScalerContext& scaler_context, 127 SkMatrix initialTransfom, 128 uint16_t upem); 129 130 SkRect getBoundingBox(); 131 132 // fontations_ffi::ColorPainter interface. is_bounds_mode()133 virtual bool is_bounds_mode() override { return true; } 134 virtual void push_transform(const fontations_ffi::Transform& transform) override; 135 virtual void pop_transform() override; 136 virtual void push_clip_glyph(uint16_t glyph_id) override; 137 virtual void push_clip_rectangle(float x_min, float y_min, float x_max, float y_max) override; pop_clip()138 virtual void pop_clip() override {} 139 140 // Paint*Gradient equivalents: fill_solid(uint16_t palette_index,float alpha)141 virtual void fill_solid(uint16_t palette_index, float alpha) override {} fill_radial(const fontations_ffi::FillRadialParams & fill_radial_params,fontations_ffi::BridgeColorStops & stops,uint8_t)142 virtual void fill_radial(const fontations_ffi::FillRadialParams& fill_radial_params, 143 fontations_ffi::BridgeColorStops& stops, 144 uint8_t) override {} fill_linear(const fontations_ffi::FillLinearParams & fill_linear_params,fontations_ffi::BridgeColorStops & stops,uint8_t)145 virtual void fill_linear(const fontations_ffi::FillLinearParams& fill_linear_params, 146 fontations_ffi::BridgeColorStops& stops, 147 uint8_t) override {} fill_sweep(const fontations_ffi::FillSweepParams & fill_sweep_params,fontations_ffi::BridgeColorStops & stops,uint8_t extend_mode)148 virtual void fill_sweep(const fontations_ffi::FillSweepParams& fill_sweep_params, 149 fontations_ffi::BridgeColorStops& stops, 150 uint8_t extend_mode) override {} 151 push_layer(uint8_t)152 virtual void push_layer(uint8_t) override {} pop_layer()153 virtual void pop_layer() override {} 154 155 // Stubs for optimized calls. We're only interested in the glyph bounds, so we forward this to 156 // push_clip_glyph() 157 virtual void fill_glyph_solid(uint16_t glyph_id, uint16_t, float) override; 158 virtual void fill_glyph_radial(uint16_t glyph_id, 159 const fontations_ffi::Transform&, 160 const fontations_ffi::FillRadialParams&, 161 fontations_ffi::BridgeColorStops&, 162 uint8_t) override; 163 virtual void fill_glyph_linear(uint16_t glyph_id, 164 const fontations_ffi::Transform&, 165 const fontations_ffi::FillLinearParams&, 166 fontations_ffi::BridgeColorStops&, 167 uint8_t) override; 168 virtual void fill_glyph_sweep(uint16_t glyph_id, 169 const fontations_ffi::Transform&, 170 const fontations_ffi::FillSweepParams&, 171 fontations_ffi::BridgeColorStops&, 172 uint8_t) override; 173 174 private: 175 SkFontationsScalerContext& fScalerContext; 176 skia_private::STArray<4, SkMatrix> fMatrixStack; 177 178 uint16_t fUpem; 179 SkRect fBounds; 180 }; 181 182 } // namespace sk_fontations 183 184 /** SkTypeface implementation based on Google Fonts Fontations Rust libraries. */ 185 class SkTypeface_Fontations : public SkTypeface { 186 private: 187 SkTypeface_Fontations(sk_sp<SkData> fontData, 188 const SkFontStyle& style, 189 uint32_t ttcIndex, 190 rust::Box<fontations_ffi::BridgeFontRef>&& fontRef, 191 rust::Box<fontations_ffi::BridgeMappingIndex>&& mappingIndex, 192 rust::Box<fontations_ffi::BridgeNormalizedCoords>&& normalizedCoords, 193 rust::Box<fontations_ffi::BridgeOutlineCollection>&& outlines, 194 rust::Vec<uint32_t>&& palette); 195 196 public: getBridgeFontRef()197 const fontations_ffi::BridgeFontRef& getBridgeFontRef() { return *fBridgeFontRef; } getBridgeNormalizedCoords()198 const fontations_ffi::BridgeNormalizedCoords& getBridgeNormalizedCoords() { 199 return *fBridgeNormalizedCoords; 200 } getOutlines()201 const fontations_ffi::BridgeOutlineCollection& getOutlines() { return *fOutlines; } getPalette()202 SkSpan<const SkColor> getPalette() const { 203 return SkSpan(reinterpret_cast<const SkColor*>(fPalette.data()), fPalette.size()); 204 } 205 206 static constexpr SkTypeface::FactoryId FactoryId = SkSetFourByteTag('f', 'n', 't', 'a'); 207 208 static sk_sp<SkTypeface> MakeFromData(sk_sp<SkData> fontData, const SkFontArguments&); 209 static sk_sp<SkTypeface> MakeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&); 210 211 protected: 212 std::unique_ptr<SkStreamAsset> onOpenStream(int* ttcIndex) const override; 213 sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override; 214 std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects& effects, 215 const SkDescriptor* desc) const override; 216 std::unique_ptr<SkScalerContext> onCreateScalerContextAsProxyTypeface( 217 const SkScalerContextEffects&, 218 const SkDescriptor*, 219 sk_sp<SkTypeface>) const override; 220 void onFilterRec(SkScalerContextRec*) const override; 221 std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override; 222 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; 223 void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override; 224 int onCountGlyphs() const override; getPostScriptGlyphNames(SkString *)225 void getPostScriptGlyphNames(SkString*) const override {} 226 void getGlyphToUnicodeMap(SkUnichar*) const override; 227 int onGetUPEM() const override; 228 void onGetFamilyName(SkString* familyName) const override; 229 bool onGetPostScriptName(SkString*) const override; 230 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; 231 bool onGlyphMaskNeedsCurrentColor() const override; 232 int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[], 233 int coordinateCount) const override; 234 int onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[], 235 int parameterCount) const override; 236 int onGetTableTags(SkFontTableTag tags[]) const override; 237 size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override; 238 239 private: 240 sk_sp<SkData> fFontData; 241 // Incoming ttc index requested when this typeface was instantiated from data. 242 uint32_t fTtcIndex = 0; 243 // fBridgeFontRef accesses the data in fFontData. fFontData needs to be kept around for the 244 // lifetime of fBridgeFontRef to safely request parsed data. 245 rust::Box<fontations_ffi::BridgeFontRef> fBridgeFontRef; 246 rust::Box<fontations_ffi::BridgeMappingIndex> fMappingIndex; 247 rust::Box<fontations_ffi::BridgeNormalizedCoords> fBridgeNormalizedCoords; 248 rust::Box<fontations_ffi::BridgeOutlineCollection> fOutlines; 249 rust::Vec<uint32_t> fPalette; 250 251 mutable SkOnce fGlyphMasksMayNeedCurrentColorOnce; 252 mutable bool fGlyphMasksMayNeedCurrentColor; 253 }; 254 255 #endif // SkTypeface_Fontations_DEFINED 256