xref: /aosp_15_r20/external/fonttools/Lib/fontTools/pens/momentsPen.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1from fontTools.pens.basePen import BasePen, OpenContourError
2
3try:
4    import cython
5
6    COMPILED = cython.compiled
7except (AttributeError, ImportError):
8    # if cython not installed, use mock module with no-op decorators and types
9    from fontTools.misc import cython
10
11    COMPILED = False
12
13
14__all__ = ["MomentsPen"]
15
16
17class MomentsPen(BasePen):
18    def __init__(self, glyphset=None):
19        BasePen.__init__(self, glyphset)
20
21        self.area = 0
22        self.momentX = 0
23        self.momentY = 0
24        self.momentXX = 0
25        self.momentXY = 0
26        self.momentYY = 0
27
28    def _moveTo(self, p0):
29        self.__startPoint = p0
30
31    def _closePath(self):
32        p0 = self._getCurrentPoint()
33        if p0 != self.__startPoint:
34            self._lineTo(self.__startPoint)
35
36    def _endPath(self):
37        p0 = self._getCurrentPoint()
38        if p0 != self.__startPoint:
39            raise OpenContourError("Glyph statistics not defined on open contours.")
40
41    @cython.locals(r0=cython.double)
42    @cython.locals(r1=cython.double)
43    @cython.locals(r2=cython.double)
44    @cython.locals(r3=cython.double)
45    @cython.locals(r4=cython.double)
46    @cython.locals(r5=cython.double)
47    @cython.locals(r6=cython.double)
48    @cython.locals(r7=cython.double)
49    @cython.locals(r8=cython.double)
50    @cython.locals(r9=cython.double)
51    @cython.locals(r10=cython.double)
52    @cython.locals(r11=cython.double)
53    @cython.locals(r12=cython.double)
54    @cython.locals(x0=cython.double, y0=cython.double)
55    @cython.locals(x1=cython.double, y1=cython.double)
56    def _lineTo(self, p1):
57        x0, y0 = self._getCurrentPoint()
58        x1, y1 = p1
59
60        r0 = x1 * y0
61        r1 = x1 * y1
62        r2 = x1**2
63        r3 = r2 * y1
64        r4 = y0 - y1
65        r5 = r4 * x0
66        r6 = x0**2
67        r7 = 2 * y0
68        r8 = y0**2
69        r9 = y1**2
70        r10 = x1**3
71        r11 = y0**3
72        r12 = y1**3
73
74        self.area += -r0 / 2 - r1 / 2 + x0 * (y0 + y1) / 2
75        self.momentX += -r2 * y0 / 6 - r3 / 3 - r5 * x1 / 6 + r6 * (r7 + y1) / 6
76        self.momentY += (
77            -r0 * y1 / 6 - r8 * x1 / 6 - r9 * x1 / 6 + x0 * (r8 + r9 + y0 * y1) / 6
78        )
79        self.momentXX += (
80            -r10 * y0 / 12
81            - r10 * y1 / 4
82            - r2 * r5 / 12
83            - r4 * r6 * x1 / 12
84            + x0**3 * (3 * y0 + y1) / 12
85        )
86        self.momentXY += (
87            -r2 * r8 / 24
88            - r2 * r9 / 8
89            - r3 * r7 / 24
90            + r6 * (r7 * y1 + 3 * r8 + r9) / 24
91            - x0 * x1 * (r8 - r9) / 12
92        )
93        self.momentYY += (
94            -r0 * r9 / 12
95            - r1 * r8 / 12
96            - r11 * x1 / 12
97            - r12 * x1 / 12
98            + x0 * (r11 + r12 + r8 * y1 + r9 * y0) / 12
99        )
100
101    @cython.locals(r0=cython.double)
102    @cython.locals(r1=cython.double)
103    @cython.locals(r2=cython.double)
104    @cython.locals(r3=cython.double)
105    @cython.locals(r4=cython.double)
106    @cython.locals(r5=cython.double)
107    @cython.locals(r6=cython.double)
108    @cython.locals(r7=cython.double)
109    @cython.locals(r8=cython.double)
110    @cython.locals(r9=cython.double)
111    @cython.locals(r10=cython.double)
112    @cython.locals(r11=cython.double)
113    @cython.locals(r12=cython.double)
114    @cython.locals(r13=cython.double)
115    @cython.locals(r14=cython.double)
116    @cython.locals(r15=cython.double)
117    @cython.locals(r16=cython.double)
118    @cython.locals(r17=cython.double)
119    @cython.locals(r18=cython.double)
120    @cython.locals(r19=cython.double)
121    @cython.locals(r20=cython.double)
122    @cython.locals(r21=cython.double)
123    @cython.locals(r22=cython.double)
124    @cython.locals(r23=cython.double)
125    @cython.locals(r24=cython.double)
126    @cython.locals(r25=cython.double)
127    @cython.locals(r26=cython.double)
128    @cython.locals(r27=cython.double)
129    @cython.locals(r28=cython.double)
130    @cython.locals(r29=cython.double)
131    @cython.locals(r30=cython.double)
132    @cython.locals(r31=cython.double)
133    @cython.locals(r32=cython.double)
134    @cython.locals(r33=cython.double)
135    @cython.locals(r34=cython.double)
136    @cython.locals(r35=cython.double)
137    @cython.locals(r36=cython.double)
138    @cython.locals(r37=cython.double)
139    @cython.locals(r38=cython.double)
140    @cython.locals(r39=cython.double)
141    @cython.locals(r40=cython.double)
142    @cython.locals(r41=cython.double)
143    @cython.locals(r42=cython.double)
144    @cython.locals(r43=cython.double)
145    @cython.locals(r44=cython.double)
146    @cython.locals(r45=cython.double)
147    @cython.locals(r46=cython.double)
148    @cython.locals(r47=cython.double)
149    @cython.locals(r48=cython.double)
150    @cython.locals(r49=cython.double)
151    @cython.locals(r50=cython.double)
152    @cython.locals(r51=cython.double)
153    @cython.locals(r52=cython.double)
154    @cython.locals(r53=cython.double)
155    @cython.locals(x0=cython.double, y0=cython.double)
156    @cython.locals(x1=cython.double, y1=cython.double)
157    @cython.locals(x2=cython.double, y2=cython.double)
158    def _qCurveToOne(self, p1, p2):
159        x0, y0 = self._getCurrentPoint()
160        x1, y1 = p1
161        x2, y2 = p2
162
163        r0 = 2 * y1
164        r1 = r0 * x2
165        r2 = x2 * y2
166        r3 = 3 * r2
167        r4 = 2 * x1
168        r5 = 3 * y0
169        r6 = x1**2
170        r7 = x2**2
171        r8 = 4 * y1
172        r9 = 10 * y2
173        r10 = 2 * y2
174        r11 = r4 * x2
175        r12 = x0**2
176        r13 = 10 * y0
177        r14 = r4 * y2
178        r15 = x2 * y0
179        r16 = 4 * x1
180        r17 = r0 * x1 + r2
181        r18 = r2 * r8
182        r19 = y1**2
183        r20 = 2 * r19
184        r21 = y2**2
185        r22 = r21 * x2
186        r23 = 5 * r22
187        r24 = y0**2
188        r25 = y0 * y2
189        r26 = 5 * r24
190        r27 = x1**3
191        r28 = x2**3
192        r29 = 30 * y1
193        r30 = 6 * y1
194        r31 = 10 * r7 * x1
195        r32 = 5 * y2
196        r33 = 12 * r6
197        r34 = 30 * x1
198        r35 = x1 * y1
199        r36 = r3 + 20 * r35
200        r37 = 12 * x1
201        r38 = 20 * r6
202        r39 = 8 * r6 * y1
203        r40 = r32 * r7
204        r41 = 60 * y1
205        r42 = 20 * r19
206        r43 = 4 * r19
207        r44 = 15 * r21
208        r45 = 12 * x2
209        r46 = 12 * y2
210        r47 = 6 * x1
211        r48 = 8 * r19 * x1 + r23
212        r49 = 8 * y1**3
213        r50 = y2**3
214        r51 = y0**3
215        r52 = 10 * y1
216        r53 = 12 * y1
217
218        self.area += (
219            -r1 / 6
220            - r3 / 6
221            + x0 * (r0 + r5 + y2) / 6
222            + x1 * y2 / 3
223            - y0 * (r4 + x2) / 6
224        )
225        self.momentX += (
226            -r11 * (-r10 + y1) / 30
227            + r12 * (r13 + r8 + y2) / 30
228            + r6 * y2 / 15
229            - r7 * r8 / 30
230            - r7 * r9 / 30
231            + x0 * (r14 - r15 - r16 * y0 + r17) / 30
232            - y0 * (r11 + 2 * r6 + r7) / 30
233        )
234        self.momentY += (
235            -r18 / 30
236            - r20 * x2 / 30
237            - r23 / 30
238            - r24 * (r16 + x2) / 30
239            + x0 * (r0 * y2 + r20 + r21 + r25 + r26 + r8 * y0) / 30
240            + x1 * y2 * (r10 + y1) / 15
241            - y0 * (r1 + r17) / 30
242        )
243        self.momentXX += (
244            r12 * (r1 - 5 * r15 - r34 * y0 + r36 + r9 * x1) / 420
245            + 2 * r27 * y2 / 105
246            - r28 * r29 / 420
247            - r28 * y2 / 4
248            - r31 * (r0 - 3 * y2) / 420
249            - r6 * x2 * (r0 - r32) / 105
250            + x0**3 * (r30 + 21 * y0 + y2) / 84
251            - x0
252            * (
253                r0 * r7
254                + r15 * r37
255                - r2 * r37
256                - r33 * y2
257                + r38 * y0
258                - r39
259                - r40
260                + r5 * r7
261            )
262            / 420
263            - y0 * (8 * r27 + 5 * r28 + r31 + r33 * x2) / 420
264        )
265        self.momentXY += (
266            r12 * (r13 * y2 + 3 * r21 + 105 * r24 + r41 * y0 + r42 + r46 * y1) / 840
267            - r16 * x2 * (r43 - r44) / 840
268            - r21 * r7 / 8
269            - r24 * (r38 + r45 * x1 + 3 * r7) / 840
270            - r41 * r7 * y2 / 840
271            - r42 * r7 / 840
272            + r6 * y2 * (r32 + r8) / 210
273            + x0
274            * (
275                -r15 * r8
276                + r16 * r25
277                + r18
278                + r21 * r47
279                - r24 * r34
280                - r26 * x2
281                + r35 * r46
282                + r48
283            )
284            / 420
285            - y0 * (r16 * r2 + r30 * r7 + r35 * r45 + r39 + r40) / 420
286        )
287        self.momentYY += (
288            -r2 * r42 / 420
289            - r22 * r29 / 420
290            - r24 * (r14 + r36 + r52 * x2) / 420
291            - r49 * x2 / 420
292            - r50 * x2 / 12
293            - r51 * (r47 + x2) / 84
294            + x0
295            * (
296                r19 * r46
297                + r21 * r5
298                + r21 * r52
299                + r24 * r29
300                + r25 * r53
301                + r26 * y2
302                + r42 * y0
303                + r49
304                + 5 * r50
305                + 35 * r51
306            )
307            / 420
308            + x1 * y2 * (r43 + r44 + r9 * y1) / 210
309            - y0 * (r19 * r45 + r2 * r53 - r21 * r4 + r48) / 420
310        )
311
312    @cython.locals(r0=cython.double)
313    @cython.locals(r1=cython.double)
314    @cython.locals(r2=cython.double)
315    @cython.locals(r3=cython.double)
316    @cython.locals(r4=cython.double)
317    @cython.locals(r5=cython.double)
318    @cython.locals(r6=cython.double)
319    @cython.locals(r7=cython.double)
320    @cython.locals(r8=cython.double)
321    @cython.locals(r9=cython.double)
322    @cython.locals(r10=cython.double)
323    @cython.locals(r11=cython.double)
324    @cython.locals(r12=cython.double)
325    @cython.locals(r13=cython.double)
326    @cython.locals(r14=cython.double)
327    @cython.locals(r15=cython.double)
328    @cython.locals(r16=cython.double)
329    @cython.locals(r17=cython.double)
330    @cython.locals(r18=cython.double)
331    @cython.locals(r19=cython.double)
332    @cython.locals(r20=cython.double)
333    @cython.locals(r21=cython.double)
334    @cython.locals(r22=cython.double)
335    @cython.locals(r23=cython.double)
336    @cython.locals(r24=cython.double)
337    @cython.locals(r25=cython.double)
338    @cython.locals(r26=cython.double)
339    @cython.locals(r27=cython.double)
340    @cython.locals(r28=cython.double)
341    @cython.locals(r29=cython.double)
342    @cython.locals(r30=cython.double)
343    @cython.locals(r31=cython.double)
344    @cython.locals(r32=cython.double)
345    @cython.locals(r33=cython.double)
346    @cython.locals(r34=cython.double)
347    @cython.locals(r35=cython.double)
348    @cython.locals(r36=cython.double)
349    @cython.locals(r37=cython.double)
350    @cython.locals(r38=cython.double)
351    @cython.locals(r39=cython.double)
352    @cython.locals(r40=cython.double)
353    @cython.locals(r41=cython.double)
354    @cython.locals(r42=cython.double)
355    @cython.locals(r43=cython.double)
356    @cython.locals(r44=cython.double)
357    @cython.locals(r45=cython.double)
358    @cython.locals(r46=cython.double)
359    @cython.locals(r47=cython.double)
360    @cython.locals(r48=cython.double)
361    @cython.locals(r49=cython.double)
362    @cython.locals(r50=cython.double)
363    @cython.locals(r51=cython.double)
364    @cython.locals(r52=cython.double)
365    @cython.locals(r53=cython.double)
366    @cython.locals(r54=cython.double)
367    @cython.locals(r55=cython.double)
368    @cython.locals(r56=cython.double)
369    @cython.locals(r57=cython.double)
370    @cython.locals(r58=cython.double)
371    @cython.locals(r59=cython.double)
372    @cython.locals(r60=cython.double)
373    @cython.locals(r61=cython.double)
374    @cython.locals(r62=cython.double)
375    @cython.locals(r63=cython.double)
376    @cython.locals(r64=cython.double)
377    @cython.locals(r65=cython.double)
378    @cython.locals(r66=cython.double)
379    @cython.locals(r67=cython.double)
380    @cython.locals(r68=cython.double)
381    @cython.locals(r69=cython.double)
382    @cython.locals(r70=cython.double)
383    @cython.locals(r71=cython.double)
384    @cython.locals(r72=cython.double)
385    @cython.locals(r73=cython.double)
386    @cython.locals(r74=cython.double)
387    @cython.locals(r75=cython.double)
388    @cython.locals(r76=cython.double)
389    @cython.locals(r77=cython.double)
390    @cython.locals(r78=cython.double)
391    @cython.locals(r79=cython.double)
392    @cython.locals(r80=cython.double)
393    @cython.locals(r81=cython.double)
394    @cython.locals(r82=cython.double)
395    @cython.locals(r83=cython.double)
396    @cython.locals(r84=cython.double)
397    @cython.locals(r85=cython.double)
398    @cython.locals(r86=cython.double)
399    @cython.locals(r87=cython.double)
400    @cython.locals(r88=cython.double)
401    @cython.locals(r89=cython.double)
402    @cython.locals(r90=cython.double)
403    @cython.locals(r91=cython.double)
404    @cython.locals(r92=cython.double)
405    @cython.locals(r93=cython.double)
406    @cython.locals(r94=cython.double)
407    @cython.locals(r95=cython.double)
408    @cython.locals(r96=cython.double)
409    @cython.locals(r97=cython.double)
410    @cython.locals(r98=cython.double)
411    @cython.locals(r99=cython.double)
412    @cython.locals(r100=cython.double)
413    @cython.locals(r101=cython.double)
414    @cython.locals(r102=cython.double)
415    @cython.locals(r103=cython.double)
416    @cython.locals(r104=cython.double)
417    @cython.locals(r105=cython.double)
418    @cython.locals(r106=cython.double)
419    @cython.locals(r107=cython.double)
420    @cython.locals(r108=cython.double)
421    @cython.locals(r109=cython.double)
422    @cython.locals(r110=cython.double)
423    @cython.locals(r111=cython.double)
424    @cython.locals(r112=cython.double)
425    @cython.locals(r113=cython.double)
426    @cython.locals(r114=cython.double)
427    @cython.locals(r115=cython.double)
428    @cython.locals(r116=cython.double)
429    @cython.locals(r117=cython.double)
430    @cython.locals(r118=cython.double)
431    @cython.locals(r119=cython.double)
432    @cython.locals(r120=cython.double)
433    @cython.locals(r121=cython.double)
434    @cython.locals(r122=cython.double)
435    @cython.locals(r123=cython.double)
436    @cython.locals(r124=cython.double)
437    @cython.locals(r125=cython.double)
438    @cython.locals(r126=cython.double)
439    @cython.locals(r127=cython.double)
440    @cython.locals(r128=cython.double)
441    @cython.locals(r129=cython.double)
442    @cython.locals(r130=cython.double)
443    @cython.locals(r131=cython.double)
444    @cython.locals(r132=cython.double)
445    @cython.locals(x0=cython.double, y0=cython.double)
446    @cython.locals(x1=cython.double, y1=cython.double)
447    @cython.locals(x2=cython.double, y2=cython.double)
448    @cython.locals(x3=cython.double, y3=cython.double)
449    def _curveToOne(self, p1, p2, p3):
450        x0, y0 = self._getCurrentPoint()
451        x1, y1 = p1
452        x2, y2 = p2
453        x3, y3 = p3
454
455        r0 = 6 * y2
456        r1 = r0 * x3
457        r2 = 10 * y3
458        r3 = r2 * x3
459        r4 = 3 * y1
460        r5 = 6 * x1
461        r6 = 3 * x2
462        r7 = 6 * y1
463        r8 = 3 * y2
464        r9 = x2**2
465        r10 = 45 * r9
466        r11 = r10 * y3
467        r12 = x3**2
468        r13 = r12 * y2
469        r14 = r12 * y3
470        r15 = 7 * y3
471        r16 = 15 * x3
472        r17 = r16 * x2
473        r18 = x1**2
474        r19 = 9 * r18
475        r20 = x0**2
476        r21 = 21 * y1
477        r22 = 9 * r9
478        r23 = r7 * x3
479        r24 = 9 * y2
480        r25 = r24 * x2 + r3
481        r26 = 9 * x2
482        r27 = x2 * y3
483        r28 = -r26 * y1 + 15 * r27
484        r29 = 3 * x1
485        r30 = 45 * x1
486        r31 = 12 * x3
487        r32 = 45 * r18
488        r33 = 5 * r12
489        r34 = r8 * x3
490        r35 = 105 * y0
491        r36 = 30 * y0
492        r37 = r36 * x2
493        r38 = 5 * x3
494        r39 = 15 * y3
495        r40 = 5 * y3
496        r41 = r40 * x3
497        r42 = x2 * y2
498        r43 = 18 * r42
499        r44 = 45 * y1
500        r45 = r41 + r43 + r44 * x1
501        r46 = y2 * y3
502        r47 = r46 * x3
503        r48 = y2**2
504        r49 = 45 * r48
505        r50 = r49 * x3
506        r51 = y3**2
507        r52 = r51 * x3
508        r53 = y1**2
509        r54 = 9 * r53
510        r55 = y0**2
511        r56 = 21 * x1
512        r57 = 6 * x2
513        r58 = r16 * y2
514        r59 = r39 * y2
515        r60 = 9 * r48
516        r61 = r6 * y3
517        r62 = 3 * y3
518        r63 = r36 * y2
519        r64 = y1 * y3
520        r65 = 45 * r53
521        r66 = 5 * r51
522        r67 = x2**3
523        r68 = x3**3
524        r69 = 630 * y2
525        r70 = 126 * x3
526        r71 = x1**3
527        r72 = 126 * x2
528        r73 = 63 * r9
529        r74 = r73 * x3
530        r75 = r15 * x3 + 15 * r42
531        r76 = 630 * x1
532        r77 = 14 * x3
533        r78 = 21 * r27
534        r79 = 42 * x1
535        r80 = 42 * x2
536        r81 = x1 * y2
537        r82 = 63 * r42
538        r83 = x1 * y1
539        r84 = r41 + r82 + 378 * r83
540        r85 = x2 * x3
541        r86 = r85 * y1
542        r87 = r27 * x3
543        r88 = 27 * r9
544        r89 = r88 * y2
545        r90 = 42 * r14
546        r91 = 90 * x1
547        r92 = 189 * r18
548        r93 = 378 * r18
549        r94 = r12 * y1
550        r95 = 252 * x1 * x2
551        r96 = r79 * x3
552        r97 = 30 * r85
553        r98 = r83 * x3
554        r99 = 30 * x3
555        r100 = 42 * x3
556        r101 = r42 * x1
557        r102 = r10 * y2 + 14 * r14 + 126 * r18 * y1 + r81 * r99
558        r103 = 378 * r48
559        r104 = 18 * y1
560        r105 = r104 * y2
561        r106 = y0 * y1
562        r107 = 252 * y2
563        r108 = r107 * y0
564        r109 = y0 * y3
565        r110 = 42 * r64
566        r111 = 378 * r53
567        r112 = 63 * r48
568        r113 = 27 * x2
569        r114 = r27 * y2
570        r115 = r113 * r48 + 42 * r52
571        r116 = x3 * y3
572        r117 = 54 * r42
573        r118 = r51 * x1
574        r119 = r51 * x2
575        r120 = r48 * x1
576        r121 = 21 * x3
577        r122 = r64 * x1
578        r123 = r81 * y3
579        r124 = 30 * r27 * y1 + r49 * x2 + 14 * r52 + 126 * r53 * x1
580        r125 = y2**3
581        r126 = y3**3
582        r127 = y1**3
583        r128 = y0**3
584        r129 = r51 * y2
585        r130 = r112 * y3 + r21 * r51
586        r131 = 189 * r53
587        r132 = 90 * y2
588
589        self.area += (
590            -r1 / 20
591            - r3 / 20
592            - r4 * (x2 + x3) / 20
593            + x0 * (r7 + r8 + 10 * y0 + y3) / 20
594            + 3 * x1 * (y2 + y3) / 20
595            + 3 * x2 * y3 / 10
596            - y0 * (r5 + r6 + x3) / 20
597        )
598        self.momentX += (
599            r11 / 840
600            - r13 / 8
601            - r14 / 3
602            - r17 * (-r15 + r8) / 840
603            + r19 * (r8 + 2 * y3) / 840
604            + r20 * (r0 + r21 + 56 * y0 + y3) / 168
605            + r29 * (-r23 + r25 + r28) / 840
606            - r4 * (10 * r12 + r17 + r22) / 840
607            + x0
608            * (
609                12 * r27
610                + r30 * y2
611                + r34
612                - r35 * x1
613                - r37
614                - r38 * y0
615                + r39 * x1
616                - r4 * x3
617                + r45
618            )
619            / 840
620            - y0 * (r17 + r30 * x2 + r31 * x1 + r32 + r33 + 18 * r9) / 840
621        )
622        self.momentY += (
623            -r4 * (r25 + r58) / 840
624            - r47 / 8
625            - r50 / 840
626            - r52 / 6
627            - r54 * (r6 + 2 * x3) / 840
628            - r55 * (r56 + r57 + x3) / 168
629            + x0
630            * (
631                r35 * y1
632                + r40 * y0
633                + r44 * y2
634                + 18 * r48
635                + 140 * r55
636                + r59
637                + r63
638                + 12 * r64
639                + r65
640                + r66
641            )
642            / 840
643            + x1 * (r24 * y1 + 10 * r51 + r59 + r60 + r7 * y3) / 280
644            + x2 * y3 * (r15 + r8) / 56
645            - y0 * (r16 * y1 + r31 * y2 + r44 * x2 + r45 + r61 - r62 * x1) / 840
646        )
647        self.momentXX += (
648            -r12 * r72 * (-r40 + r8) / 9240
649            + 3 * r18 * (r28 + r34 - r38 * y1 + r75) / 3080
650            + r20
651            * (
652                r24 * x3
653                - r72 * y0
654                - r76 * y0
655                - r77 * y0
656                + r78
657                + r79 * y3
658                + r80 * y1
659                + 210 * r81
660                + r84
661            )
662            / 9240
663            - r29
664            * (
665                r12 * r21
666                + 14 * r13
667                + r44 * r9
668                - r73 * y3
669                + 54 * r86
670                - 84 * r87
671                - r89
672                - r90
673            )
674            / 9240
675            - r4 * (70 * r12 * x2 + 27 * r67 + 42 * r68 + r74) / 9240
676            + 3 * r67 * y3 / 220
677            - r68 * r69 / 9240
678            - r68 * y3 / 4
679            - r70 * r9 * (-r62 + y2) / 9240
680            + 3 * r71 * (r24 + r40) / 3080
681            + x0**3 * (r24 + r44 + 165 * y0 + y3) / 660
682            + x0
683            * (
684                r100 * r27
685                + 162 * r101
686                + r102
687                + r11
688                + 63 * r18 * y3
689                + r27 * r91
690                - r33 * y0
691                - r37 * x3
692                + r43 * x3
693                - r73 * y0
694                - r88 * y1
695                + r92 * y2
696                - r93 * y0
697                - 9 * r94
698                - r95 * y0
699                - r96 * y0
700                - r97 * y1
701                - 18 * r98
702                + r99 * x1 * y3
703            )
704            / 9240
705            - y0
706            * (
707                r12 * r56
708                + r12 * r80
709                + r32 * x3
710                + 45 * r67
711                + 14 * r68
712                + 126 * r71
713                + r74
714                + r85 * r91
715                + 135 * r9 * x1
716                + r92 * x2
717            )
718            / 9240
719        )
720        self.momentXY += (
721            -r103 * r12 / 18480
722            - r12 * r51 / 8
723            - 3 * r14 * y2 / 44
724            + 3 * r18 * (r105 + r2 * y1 + 18 * r46 + 15 * r48 + 7 * r51) / 6160
725            + r20
726            * (
727                1260 * r106
728                + r107 * y1
729                + r108
730                + 28 * r109
731                + r110
732                + r111
733                + r112
734                + 30 * r46
735                + 2310 * r55
736                + r66
737            )
738            / 18480
739            - r54 * (7 * r12 + 18 * r85 + 15 * r9) / 18480
740            - r55 * (r33 + r73 + r93 + r95 + r96 + r97) / 18480
741            - r7 * (42 * r13 + r82 * x3 + 28 * r87 + r89 + r90) / 18480
742            - 3 * r85 * (r48 - r66) / 220
743            + 3 * r9 * y3 * (r62 + 2 * y2) / 440
744            + x0
745            * (
746                -r1 * y0
747                - 84 * r106 * x2
748                + r109 * r56
749                + 54 * r114
750                + r117 * y1
751                + 15 * r118
752                + 21 * r119
753                + 81 * r120
754                + r121 * r46
755                + 54 * r122
756                + 60 * r123
757                + r124
758                - r21 * x3 * y0
759                + r23 * y3
760                - r54 * x3
761                - r55 * r72
762                - r55 * r76
763                - r55 * r77
764                + r57 * y0 * y3
765                + r60 * x3
766                + 84 * r81 * y0
767                + 189 * r81 * y1
768            )
769            / 9240
770            + x1
771            * (
772                r104 * r27
773                - r105 * x3
774                - r113 * r53
775                + 63 * r114
776                + r115
777                - r16 * r53
778                + 28 * r47
779                + r51 * r80
780            )
781            / 3080
782            - y0
783            * (
784                54 * r101
785                + r102
786                + r116 * r5
787                + r117 * x3
788                + 21 * r13
789                - r19 * y3
790                + r22 * y3
791                + r78 * x3
792                + 189 * r83 * x2
793                + 60 * r86
794                + 81 * r9 * y1
795                + 15 * r94
796                + 54 * r98
797            )
798            / 9240
799        )
800        self.momentYY += (
801            -r103 * r116 / 9240
802            - r125 * r70 / 9240
803            - r126 * x3 / 12
804            - 3 * r127 * (r26 + r38) / 3080
805            - r128 * (r26 + r30 + x3) / 660
806            - r4 * (r112 * x3 + r115 - 14 * r119 + 84 * r47) / 9240
807            - r52 * r69 / 9240
808            - r54 * (r58 + r61 + r75) / 9240
809            - r55
810            * (r100 * y1 + r121 * y2 + r26 * y3 + r79 * y2 + r84 + 210 * x2 * y1)
811            / 9240
812            + x0
813            * (
814                r108 * y1
815                + r110 * y0
816                + r111 * y0
817                + r112 * y0
818                + 45 * r125
819                + 14 * r126
820                + 126 * r127
821                + 770 * r128
822                + 42 * r129
823                + r130
824                + r131 * y2
825                + r132 * r64
826                + 135 * r48 * y1
827                + 630 * r55 * y1
828                + 126 * r55 * y2
829                + 14 * r55 * y3
830                + r63 * y3
831                + r65 * y3
832                + r66 * y0
833            )
834            / 9240
835            + x1
836            * (
837                27 * r125
838                + 42 * r126
839                + 70 * r129
840                + r130
841                + r39 * r53
842                + r44 * r48
843                + 27 * r53 * y2
844                + 54 * r64 * y2
845            )
846            / 3080
847            + 3 * x2 * y3 * (r48 + r66 + r8 * y3) / 220
848            - y0
849            * (
850                r100 * r46
851                + 18 * r114
852                - 9 * r118
853                - 27 * r120
854                - 18 * r122
855                - 30 * r123
856                + r124
857                + r131 * x2
858                + r132 * x3 * y1
859                + 162 * r42 * y1
860                + r50
861                + 63 * r53 * x3
862                + r64 * r99
863            )
864            / 9240
865        )
866
867
868if __name__ == "__main__":
869    from fontTools.misc.symfont import x, y, printGreenPen
870
871    printGreenPen(
872        "MomentsPen",
873        [
874            ("area", 1),
875            ("momentX", x),
876            ("momentY", y),
877            ("momentXX", x**2),
878            ("momentXY", x * y),
879            ("momentYY", y**2),
880        ],
881    )
882