• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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