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