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