xref: /aosp_15_r20/external/skia/src/ports/SkTypeface_fontations_priv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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