#!/usr/bin/env python3 """Manually authored SVG study of the supplied composition; no bitmap tracing. This studies one reference composition. It is not a new scene or a generic illustration generator. Run with --out path.svg. """ import argparse from pathlib import Path from draw_paper_plane import pressure_line def draw(): black, orange, red, white = '#080808', '#FF902A', '#F04B32', '#FFFFFF' parts = [] def shape(d, fill='none', stroke=black, width=2.5): parts.append(f'') def ink(curves, width=2.6): shape(pressure_line(curves, width), black, 'none', 0) def dot(x, y, r, color=black): parts.append(f'') parts.append('') # Separate black filled edges from thin top contours. shape('M 59,336 C 81,337 111,342 137,338 C 151,327 169,310 183,299 C 187,296 189,302 186,307 C 175,319 158,338 145,348 C 139,351 124,349 114,349 L 61,348 C 57,347 59,340 59,336 Z', black, 'none') ink([((69,359),(94,360),(122,364),(145,361))], 2.7) shape('M 42,408 C 65,409 88,411 108,409 C 121,399 138,380 151,369 C 157,365 160,366 156,374 C 144,389 129,408 117,420 C 113,424 103,422 95,422 L 41,421 Z', black, 'none') ink([((42,435),(100,437),(176,444),(252,451))], 2.6) shape('M 254,459 C 240,474 215,506 192,536 C 188,542 198,540 205,539 C 211,537 238,504 255,477 Z', black, 'none') shape('M 145,411 L 196,357 L 176,355 Q 172,355 173,346 L 211,310 Q 218,303 226,305 L 345,312 Q 356,313 355,320 C 339,348 303,401 278,427 Q 273,435 264,436 L 150,426 Q 143,425 145,411 Z', black, 'none') shape('M 147,410 C 162,392 184,369 203,349 L 177,347 Q 174,347 176,342 L 211,308 Q 217,303 224,304 L 343,310 Q 354,311 352,317 C 333,350 299,392 272,419 Q 268,424 261,422 L 151,416 Q 144,416 147,410 Z', white, black, 2.6) # Hand-lettered word: actual paths instead of a platform font. parts.append('') shape('M 0,12 L 4,2 M 3,6 Q 7,0 12,3', 'none', black, 3.0) shape('M 14,8 Q 24,9 23,4 Q 20,0 16,4 Q 10,12 17,13 Q 21,14 25,11', 'none', black, 2.6) shape('M 30,0 L 26,12 Q 25,16 31,13 M 25,5 L 35,4', 'none', black, 2.7) shape('M 37,4 Q 32,15 38,14 Q 43,13 46,5 L 43,14', 'none', black, 2.7) shape('M 50,14 L 54,4 M 52,9 Q 57,2 62,5', 'none', black, 2.9) shape('M 63,14 L 67,4 L 65,10 Q 75,0 76,7 L 73,14', 'none', black, 2.7) parts.append('') parts.append('') # Rear boot sits behind the bent knee; white glint is a drawn shape. shape('M 378,230 C 384,221 398,213 405,219 C 412,225 418,243 418,256 C 420,270 413,283 403,286 C 394,289 387,280 385,270 L 376,248 Z', black, 'none') shape('M 399,263 C 402,258 405,258 403,264 L 398,271 Q 394,272 396,268 Z', white, 'none') # Most of the left orange perimeter intentionally has no black contour. shape('M 216,133 C 246,116 291,104 319,109 C 331,131 339,148 350,167 C 361,185 370,200 375,219 C 379,235 382,245 388,257 C 396,272 389,289 379,302 C 373,310 363,317 354,317 C 346,316 335,312 331,301 L 321,278 C 315,293 307,308 295,315 C 285,321 275,318 267,309 C 259,317 247,320 240,313 C 230,299 219,271 212,245 C 205,220 197,194 200,173 C 200,154 207,142 216,133 Z', orange, 'none') ink([((374,205),(381,222),(381,249),(375,273))], 3.1) ink([((377,269),(378,256),(383,249),(384,250))], 2.4) ink([((389,268),(393,287),(373,311),(355,316))], 3.0) ink([((375,202),(370,221),(345,234),(326,239))], 3.2) # White opening between the sleeves gives the body its bent silhouette. shape('M 240,204 C 251,214 268,229 280,237 C 275,258 269,280 265,297 C 258,278 247,252 245,235 Z', white, black, 2.8) ink([((240,202),(252,213),(267,228),(280,236))], 3.2) # Inner contour of the far sleeve, then the sleeve resting on the key. ink([((265,298),(263,307),(257,317),(244,317))], 3.1) ink([((244,317),(239,317),(235,307),(231,298))], 2.3) shape('M 282,197 C 281,228 276,261 269,292 C 266,303 268,311 278,315 C 289,321 299,316 304,305 C 318,275 326,242 329,213 L 332,170', orange, 'none') ink([((282,198),(283,226),(274,272),(269,291)),((269,291),(265,306),(273,314),(279,316)),((279,316),(291,323),(301,313),(306,302)),((306,302),(320,269),(328,223),(332,170))], 3.0) # Collar is a few angular ink marks, not a large black triangle. ink([((246,181),(246,184),(246,188),(247,189)),((247,189),(256,188),(265,191),(270,196))], 2.8) shape('M 254,170 C 265,176 280,172 286,165 L 275,190 L 268,192 L 265,182 Z', black, 'none') # The overlapping hands are small and follow the direction of the wrists. shape('M 242,317 C 245,319 253,320 260,316 L 266,321 C 265,327 255,333 250,335 C 246,334 246,329 244,325 Z', white, black, 2.3) shape('M 274,317 C 280,320 288,319 294,315 C 296,322 292,335 288,342 C 285,346 281,347 279,342 C 277,349 271,351 269,344 C 266,350 260,349 260,342 C 256,347 250,345 251,338 C 247,339 245,335 249,331 L 259,323 L 263,315', white, black, 2.4) ink([((257,331),(253,335),(251,339),(251,341))], 1.9) ink([((267,336),(265,339),(262,343),(261,345))], 1.8) ink([((277,337),(275,341),(273,345),(272,346))], 1.8) # Face and near-black side of the head: helmet will overlap their top. shape('M 297,113 C 310,108 321,103 325,109 C 327,126 316,146 302,158 L 288,161 Z', black, 'none') shape('M 204,137 C 216,132 239,132 257,130 L 298,124 C 304,133 306,148 303,157 C 286,172 266,179 245,177 C 226,175 211,164 204,149 Z', white, black, 2.5) ink([((299,130),(301,141),(304,150),(303,157))], 3.1) shape('M 308,133 C 311,127 316,125 316,131 C 315,137 312,141 310,140 Z', white, 'none') dot(229,160,2.3) dot(277,155,2.7) ink([((253,169),(253,171),(254,172),(256,172))], 1.6) # Uneven dome and tapering parallel bands match the reference's rhythm. shape('M 196,126 C 190,112 191,96 194,83 C 197,67 206,52 220,42 C 233,32 250,29 267,31 C 288,31 309,43 318,63 C 322,71 324,79 328,84 C 331,88 328,95 326,99 C 314,117 293,130 272,138 C 249,146 217,148 197,139 Z', white, 'none') ink([((196,126),(188,107),(192,83),(199,69)),((199,69),(206,50),(221,36),(239,33)),((239,33),(256,28),(278,31),(290,36)),((290,36),(308,44),(317,60),(321,73))], 2.8) ink([((321,73),(325,78),(331,85),(328,91)),((328,91),(318,111),(295,126),(273,135)),((273,135),(247,147),(215,148),(197,139))], 3.0) ink([((196,122),(208,129),(223,129),(237,128)),((237,128),(268,129),(304,104),(319,79))], 2.7) ink([((197,130),(209,136),(222,137),(235,136)),((235,136),(270,139),(307,111),(325,85))], 2.7) ink([((196,126),(197,130),(196,135),(197,139))], 2.8) # Irregular headlamp: black weight balances the solid black shoes. shape('M 222,128 C 225,117 235,112 242,116 C 252,120 257,130 253,139 C 250,148 241,153 233,150 C 222,147 218,139 222,128 Z', black, 'none') shape('M 229,135 C 231,129 236,128 240,131 C 245,135 244,141 240,144 C 235,148 228,143 229,135 Z', white, 'none') parts.append('') parts.append('') shape('M 320,397 C 333,384 353,373 371,367 C 381,362 391,365 404,368 L 461,381 C 470,383 476,391 476,400 L 477,422 C 474,431 461,437 449,442 L 400,463 C 389,468 377,465 366,462 L 326,447 C 313,442 312,430 313,418 C 312,411 314,404 320,397 Z', red, 'none') ink([((319,409),(334,416),(359,424),(378,429)),((378,429),(392,435),(401,433),(414,428)),((414,428),(440,419),(457,410),(468,400))], 3.1) shape('M 320,421 C 342,429 366,439 385,442 C 394,444 403,440 412,436 C 431,429 450,420 469,408 L 469,416 C 449,428 430,437 411,443 C 401,447 393,450 382,447 C 360,444 337,434 319,428 Z', black, 'none') dot(451,394,4.6) # A plain little white tool mark, not a copied brand emblem. shape('M 373,407 C 370,398 374,385 383,383 C 389,380 394,384 392,390 L 385,393 L 384,399 L 391,401 C 386,408 379,411 373,407 Z', 'none', white, 2.6) for x,y,r in [(380,377,1.4),(388,376,1.3),(398,380,1.3),(407,385,1.2),(413,392,1.2),(367,415,1.3),(377,419,1.4),(388,420,1.2),(399,416,1.2)]: dot(x,y,r,white) parts.append('') parts.append('') ink([((154,184),(152,193),(154,205),(157,209))], 2.8) ink([((161,181),(161,190),(162,198),(162,203))], 2.5) ink([((381,126),(383,131),(384,137),(384,141))], 2.5) ink([((390,123),(392,128),(392,132),(392,136))], 2.7) parts.append('') return ('\n' 'Reference composition study in hand-authored SVG\n' 'A helmeted orange worker pressing a large return key. Manually drawn paths studying a user-supplied reference; no embedded bitmap.\n' '\n' + '\n'.join(parts) + '\n\n') if __name__ == '__main__': parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--out', type=Path, required=True) args = parser.parse_args() args.out.parent.mkdir(parents=True, exist_ok=True) args.out.write_text(draw(), encoding='utf-8') print(args.out.resolve())