├── .gitignore ├── Fonts ├── Charcodes.csv ├── OpenSans-Regular.json ├── OpenSans-Regular.plist ├── OpenSans-Regular.png ├── Roboto-Medium.json ├── Roboto-Medium.plist └── Roboto-Medium.png ├── LICENSE ├── README.md ├── SCNText2D-Shaders-iOS └── SDFText.metal ├── SCNText2D-Shaders-macOS └── SDFText.metal ├── SCNText2D-iOS ├── Info.plist └── SCNText2D_iOS.h ├── SCNText2D-iOSTestApp ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── GameViewController.swift └── Info.plist ├── SCNText2D-iOSTests ├── Info.plist └── SCNText2D_iOSTests.swift ├── SCNText2D-macOS ├── Info.plist └── SCNText2D_macOS.h ├── SCNText2D-macOSTestApp ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ └── Main.storyboard ├── GameViewController.swift ├── Info.plist └── SCNText2D_macOSTestApp.entitlements ├── SCNText2D-macOSTests ├── Info.plist └── SCNText2D_macOSTests.swift ├── SCNText2D.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ ├── xcbaselines │ └── 4BF7E9AA220FDAF8002E8328.xcbaseline │ │ ├── 2102A3E8-DB19-4C1B-A499-83BAC82A6AA8.plist │ │ └── Info.plist │ └── xcschemes │ ├── SCNText2D-Shaders-iOS.xcscheme │ ├── SCNText2D-Shaders-macOS.xcscheme │ ├── SCNText2D-iOS.xcscheme │ └── SCNText2D-macOS.xcscheme └── Shared ├── AtlasData.swift ├── Font ├── crocodile_feet.json └── crocodile_feet.png ├── FontMetrics.swift ├── GlyphData.swift └── SCNText2D.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | Carthage/Checkouts 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots/**/*.png 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /Fonts/Charcodes.csv: -------------------------------------------------------------------------------- 1 | 0x0020,0x0022 2 | 0x0026,0x0029 3 | 0x002c,0x003b 4 | 0x0041,0x005d 5 | 0x0061,0x007d 6 | 0x00c0,0x00ff 7 | 0x0100,0x017f 8 | 0x1e02,0x1ef3 9 | -------------------------------------------------------------------------------- /Fonts/OpenSans-Regular.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shipyard-games/SCNText2D/88f0b4da36072e6a9537b88eab54df9b5f3893cb/Fonts/OpenSans-Regular.png -------------------------------------------------------------------------------- /Fonts/Roboto-Medium.json: -------------------------------------------------------------------------------- 1 | {"ascender":0.937500,"descender":-0.250000,"glyph_data":{" ":{"advance_x":0.249023,"bbox_height":0.187500,"bbox_width":0.187500,"bearing_x":-0.093750,"bearing_y":0.093750,"charcode":" ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"!":{"advance_x":0.268066,"bbox_height":0.905273,"bbox_width":0.322266,"bearing_x":-0.024740,"bearing_y":0.804688,"charcode":"!","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"&":{"advance_x":0.639160,"bbox_height":0.917969,"bbox_width":0.778809,"bearing_x":-0.052083,"bearing_y":0.815104,"charcode":"&","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"'":{"advance_x":0.168945,"bbox_height":0.439453,"bbox_width":0.277832,"bearing_x":-0.054688,"bearing_y":0.843750,"charcode":"'","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"(":{"advance_x":0.348633,"bbox_height":1.209961,"bbox_width":0.454102,"bearing_x":-0.031250,"bearing_y":0.890625,"charcode":"(","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},",":{"advance_x":0.219727,"bbox_height":0.462402,"bbox_width":0.344238,"bearing_x":-0.080729,"bearing_y":0.209635,"charcode":",","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"-":{"advance_x":0.328125,"bbox_height":0.283203,"bbox_width":0.443848,"bearing_x":-0.059896,"bearing_y":0.444010,"charcode":"-","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},".":{"advance_x":0.279297,"bbox_height":0.317871,"bbox_width":0.325684,"bearing_x":-0.028646,"bearing_y":0.218750,"charcode":".","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"\/":{"advance_x":0.395508,"bbox_height":0.959473,"bbox_width":0.560547,"bearing_x":-0.093750,"bearing_y":0.804688,"charcode":"\/","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"0":{"advance_x":0.568359,"bbox_height":0.917969,"bbox_width":0.652832,"bearing_x":-0.042969,"bearing_y":0.815104,"charcode":"0","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"1":{"advance_x":0.568359,"bbox_height":0.900879,"bbox_width":0.479980,"bearing_x":-0.011719,"bearing_y":0.807292,"charcode":"1","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"2":{"advance_x":0.568359,"bbox_height":0.908203,"bbox_width":0.679199,"bearing_x":-0.054688,"bearing_y":0.815104,"charcode":"2","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"3":{"advance_x":0.568359,"bbox_height":0.917969,"bbox_width":0.659180,"bearing_x":-0.055990,"bearing_y":0.815104,"charcode":"3","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"4":{"advance_x":0.568359,"bbox_height":0.898438,"bbox_width":0.705078,"bearing_x":-0.069010,"bearing_y":0.804688,"charcode":"4","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"5":{"advance_x":0.568359,"bbox_height":0.908203,"bbox_width":0.652832,"bearing_x":-0.031250,"bearing_y":0.804688,"charcode":"5","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"6":{"advance_x":0.568359,"bbox_height":0.911621,"bbox_width":0.657227,"bearing_x":-0.037760,"bearing_y":0.808594,"charcode":"6","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"7":{"advance_x":0.568359,"bbox_height":0.898438,"bbox_width":0.680176,"bearing_x":-0.061198,"bearing_y":0.804688,"charcode":"7","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"8":{"advance_x":0.568359,"bbox_height":0.917969,"bbox_width":0.653320,"bearing_x":-0.042969,"bearing_y":0.815104,"charcode":"8","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"9":{"advance_x":0.568359,"bbox_height":0.911133,"bbox_width":0.650879,"bearing_x":-0.049479,"bearing_y":0.815104,"charcode":"9","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},":":{"advance_x":0.265137,"bbox_height":0.732422,"bbox_width":0.325684,"bearing_x":-0.031250,"bearing_y":0.634115,"charcode":":","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"A":{"advance_x":0.665527,"bbox_height":0.898438,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.804688,"charcode":"A","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"B":{"advance_x":0.630859,"bbox_height":0.898438,"bbox_width":0.694824,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"B","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"C":{"advance_x":0.652832,"bbox_height":0.917969,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":0.815104,"charcode":"C","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"D":{"advance_x":0.653320,"bbox_height":0.898438,"bbox_width":0.717773,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"D","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"E":{"advance_x":0.565430,"bbox_height":0.898438,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"E","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"F":{"advance_x":0.549316,"bbox_height":0.898438,"bbox_width":0.639160,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"F","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"G":{"advance_x":0.680664,"bbox_height":0.917969,"bbox_width":0.752930,"bearing_x":-0.042969,"bearing_y":0.815104,"charcode":"G","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"H":{"advance_x":0.710449,"bbox_height":0.898438,"bbox_width":0.751953,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"H","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"I":{"advance_x":0.282227,"bbox_height":0.898438,"bbox_width":0.310547,"bearing_x":-0.014323,"bearing_y":0.804688,"charcode":"I","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"J":{"advance_x":0.555176,"bbox_height":0.908203,"bbox_width":0.651855,"bearing_x":-0.072917,"bearing_y":0.804688,"charcode":"J","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"K":{"advance_x":0.630371,"bbox_height":0.898438,"bbox_width":0.751953,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"K","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"L":{"advance_x":0.541016,"bbox_height":0.898438,"bbox_width":0.633789,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"L","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"M":{"advance_x":0.875488,"bbox_height":0.898438,"bbox_width":0.916992,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"M","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"N":{"advance_x":0.709961,"bbox_height":0.898438,"bbox_width":0.751465,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"N","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"O":{"advance_x":0.690430,"bbox_height":0.917969,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.815104,"charcode":"O","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"P":{"advance_x":0.639160,"bbox_height":0.898438,"bbox_width":0.718750,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"P","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Q":{"advance_x":0.690430,"bbox_height":1.031250,"bbox_width":0.778320,"bearing_x":-0.046875,"bearing_y":0.815104,"charcode":"Q","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"R":{"advance_x":0.624023,"bbox_height":0.898438,"bbox_width":0.723633,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"R","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"S":{"advance_x":0.603516,"bbox_height":0.917969,"bbox_width":0.718750,"bearing_x":-0.058594,"bearing_y":0.815104,"charcode":"S","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"T":{"advance_x":0.606934,"bbox_height":0.898438,"bbox_width":0.751465,"bearing_x":-0.072917,"bearing_y":0.804688,"charcode":"T","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"U":{"advance_x":0.651855,"bbox_height":0.908203,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.804688,"charcode":"U","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"V":{"advance_x":0.646973,"bbox_height":0.898438,"bbox_width":0.817871,"bearing_x":-0.085938,"bearing_y":0.804688,"charcode":"V","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"W":{"advance_x":0.879883,"bbox_height":0.898438,"bbox_width":1.025879,"bearing_x":-0.070312,"bearing_y":0.804688,"charcode":"W","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"X":{"advance_x":0.632812,"bbox_height":0.898438,"bbox_width":0.781250,"bearing_x":-0.074219,"bearing_y":0.804688,"charcode":"X","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Y":{"advance_x":0.609375,"bbox_height":0.898438,"bbox_width":0.788574,"bearing_x":-0.091146,"bearing_y":0.804688,"charcode":"Y","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Z":{"advance_x":0.602051,"bbox_height":0.898438,"bbox_width":0.716797,"bearing_x":-0.054688,"bearing_y":0.804688,"charcode":"Z","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"[":{"advance_x":0.273926,"bbox_height":1.165039,"bbox_width":0.386719,"bearing_x":-0.029948,"bearing_y":0.914062,"charcode":"[","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"\\":{"advance_x":0.417969,"bbox_height":0.959473,"bbox_width":0.601562,"bearing_x":-0.084635,"bearing_y":0.804688,"charcode":"\\","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"a":{"advance_x":0.541016,"bbox_height":0.735352,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.632812,"charcode":"a","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"b":{"advance_x":0.562988,"bbox_height":0.947266,"bbox_width":0.651367,"bearing_x":-0.033854,"bearing_y":0.843750,"charcode":"b","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"c":{"advance_x":0.523438,"bbox_height":0.735352,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"c","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"d":{"advance_x":0.564453,"bbox_height":0.947266,"bbox_width":0.650391,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"d","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"e":{"advance_x":0.536621,"bbox_height":0.735352,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.632812,"charcode":"e","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"f":{"advance_x":0.354492,"bbox_height":0.947754,"bbox_width":0.520020,"bearing_x":-0.072917,"bearing_y":0.854167,"charcode":"f","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"g":{"advance_x":0.566895,"bbox_height":0.933594,"bbox_width":0.653320,"bearing_x":-0.054688,"bearing_y":0.632812,"charcode":"g","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"h":{"advance_x":0.555176,"bbox_height":0.937500,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.843750,"charcode":"h","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"i":{"advance_x":0.255371,"bbox_height":0.916504,"bbox_width":0.321777,"bearing_x":-0.033854,"bearing_y":0.822917,"charcode":"i","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"j":{"advance_x":0.250488,"bbox_height":1.129883,"bbox_width":0.414062,"bearing_x":-0.131510,"bearing_y":0.822917,"charcode":"j","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"k":{"advance_x":0.521973,"bbox_height":0.937500,"bbox_width":0.652832,"bearing_x":-0.033854,"bearing_y":0.843750,"charcode":"k","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"l":{"advance_x":0.255371,"bbox_height":0.937500,"bbox_width":0.306152,"bearing_x":-0.026042,"bearing_y":0.843750,"charcode":"l","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"m":{"advance_x":0.870117,"bbox_height":0.725586,"bbox_width":0.936035,"bearing_x":-0.033854,"bearing_y":0.632812,"charcode":"m","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"n":{"advance_x":0.556152,"bbox_height":0.725586,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.632812,"charcode":"n","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"o":{"advance_x":0.569336,"bbox_height":0.735352,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"o","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"p":{"advance_x":0.562988,"bbox_height":0.928711,"bbox_width":0.650391,"bearing_x":-0.033854,"bearing_y":0.632812,"charcode":"p","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"q":{"advance_x":0.567871,"bbox_height":0.928711,"bbox_width":0.649902,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"q","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"r":{"advance_x":0.351562,"bbox_height":0.725586,"bbox_width":0.464844,"bearing_x":-0.033854,"bearing_y":0.632812,"charcode":"r","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"s":{"advance_x":0.516113,"bbox_height":0.735352,"bbox_width":0.624512,"bearing_x":-0.057292,"bearing_y":0.632812,"charcode":"s","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"t":{"advance_x":0.332520,"bbox_height":0.854004,"bbox_width":0.489258,"bearing_x":-0.089844,"bearing_y":0.751302,"charcode":"t","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"u":{"advance_x":0.555664,"bbox_height":0.725586,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.622396,"charcode":"u","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"v":{"advance_x":0.494629,"bbox_height":0.715820,"bbox_width":0.658203,"bearing_x":-0.083333,"bearing_y":0.622396,"charcode":"v","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"w":{"advance_x":0.743164,"bbox_height":0.715820,"bbox_width":0.895996,"bearing_x":-0.078125,"bearing_y":0.622396,"charcode":"w","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"x":{"advance_x":0.502930,"bbox_height":0.715820,"bbox_width":0.660645,"bearing_x":-0.079427,"bearing_y":0.622396,"charcode":"x","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"y":{"advance_x":0.486816,"bbox_height":0.929199,"bbox_width":0.661133,"bearing_x":-0.088542,"bearing_y":0.622396,"charcode":"y","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"z":{"advance_x":0.502930,"bbox_height":0.715820,"bbox_width":0.616211,"bearing_x":-0.054688,"bearing_y":0.622396,"charcode":"z","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"{":{"advance_x":0.335449,"bbox_height":1.143066,"bbox_width":0.480957,"bearing_x":-0.066406,"bearing_y":0.873698,"charcode":"{","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"|":{"advance_x":0.250977,"bbox_height":1.030273,"bbox_width":0.269043,"bearing_x":-0.009115,"bearing_y":0.804688,"charcode":"|","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"À":{"advance_x":0.665527,"bbox_height":1.088867,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.996094,"charcode":"À","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Á":{"advance_x":0.665527,"bbox_height":1.088867,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.996094,"charcode":"Á","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Â":{"advance_x":0.665527,"bbox_height":1.089355,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.996094,"charcode":"Â","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ã":{"advance_x":0.665527,"bbox_height":1.083984,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.990885,"charcode":"Ã","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ä":{"advance_x":0.665527,"bbox_height":1.063477,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.970052,"charcode":"Ä","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Å":{"advance_x":0.665527,"bbox_height":1.134766,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.041667,"charcode":"Å","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Æ":{"advance_x":0.939941,"bbox_height":0.898438,"bbox_width":1.109863,"bearing_x":-0.098958,"bearing_y":0.804688,"charcode":"Æ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ç":{"advance_x":0.652832,"bbox_height":1.128906,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":0.815104,"charcode":"Ç","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"È":{"advance_x":0.565430,"bbox_height":1.092285,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.998698,"charcode":"È","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"É":{"advance_x":0.565430,"bbox_height":1.092285,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.998698,"charcode":"É","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ê":{"advance_x":0.565430,"bbox_height":1.092773,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":1,"charcode":"Ê","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ë":{"advance_x":0.565430,"bbox_height":1.066895,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.973958,"charcode":"Ë","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ì":{"advance_x":0.282227,"bbox_height":1.092285,"bbox_width":0.417969,"bearing_x":-0.121094,"bearing_y":0.998698,"charcode":"Ì","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Í":{"advance_x":0.282227,"bbox_height":1.092285,"bbox_width":0.418945,"bearing_x":-0.014323,"bearing_y":0.998698,"charcode":"Í","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Î":{"advance_x":0.282227,"bbox_height":1.092773,"bbox_width":0.522949,"bearing_x":-0.119792,"bearing_y":1,"charcode":"Î","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ï":{"advance_x":0.282227,"bbox_height":1.066895,"bbox_width":0.534180,"bearing_x":-0.126302,"bearing_y":0.973958,"charcode":"Ï","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ð":{"advance_x":0.667969,"bbox_height":0.898438,"bbox_width":0.809082,"bearing_x":-0.098958,"bearing_y":0.804688,"charcode":"Ð","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ñ":{"advance_x":0.709961,"bbox_height":1.083984,"bbox_width":0.751465,"bearing_x":-0.022135,"bearing_y":0.990885,"charcode":"Ñ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ò":{"advance_x":0.690430,"bbox_height":1.098633,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.996094,"charcode":"Ò","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ó":{"advance_x":0.690430,"bbox_height":1.098633,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.996094,"charcode":"Ó","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ô":{"advance_x":0.690430,"bbox_height":1.099121,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.996094,"charcode":"Ô","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Õ":{"advance_x":0.690430,"bbox_height":1.093750,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.990885,"charcode":"Õ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ö":{"advance_x":0.690430,"bbox_height":1.073242,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.970052,"charcode":"Ö","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"×":{"advance_x":0.533203,"bbox_height":0.648438,"bbox_width":0.640137,"bearing_x":-0.057292,"bearing_y":0.660156,"charcode":"×","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ø":{"advance_x":0.689453,"bbox_height":0.975098,"bbox_width":0.777832,"bearing_x":-0.042969,"bearing_y":0.835938,"charcode":"Ø","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ù":{"advance_x":0.651855,"bbox_height":1.098633,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.996094,"charcode":"Ù","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ú":{"advance_x":0.651855,"bbox_height":1.098633,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.996094,"charcode":"Ú","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Û":{"advance_x":0.651855,"bbox_height":1.099121,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.996094,"charcode":"Û","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ü":{"advance_x":0.651855,"bbox_height":1.073242,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.970052,"charcode":"Ü","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ý":{"advance_x":0.609375,"bbox_height":1.088867,"bbox_width":0.788574,"bearing_x":-0.091146,"bearing_y":0.996094,"charcode":"Ý","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Þ":{"advance_x":0.598633,"bbox_height":0.898438,"bbox_width":0.676758,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Þ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ß":{"advance_x":0.612793,"bbox_height":0.957520,"bbox_width":0.696777,"bearing_x":-0.027344,"bearing_y":0.854167,"charcode":"ß","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"à":{"advance_x":0.541016,"bbox_height":0.947266,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.843750,"charcode":"à","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"á":{"advance_x":0.541016,"bbox_height":0.947266,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.843750,"charcode":"á","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"â":{"advance_x":0.541016,"bbox_height":0.947754,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.845052,"charcode":"â","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ã":{"advance_x":0.541016,"bbox_height":0.942383,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.839844,"charcode":"ã","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ä":{"advance_x":0.541016,"bbox_height":0.921875,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.819010,"charcode":"ä","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"å":{"advance_x":0.541016,"bbox_height":0.993164,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.890625,"charcode":"å","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"æ":{"advance_x":0.844238,"bbox_height":0.736328,"bbox_width":0.966797,"bearing_x":-0.058594,"bearing_y":0.632812,"charcode":"æ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ç":{"advance_x":0.523438,"bbox_height":0.946289,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"ç","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"è":{"advance_x":0.536621,"bbox_height":0.947266,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.843750,"charcode":"è","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"é":{"advance_x":0.536621,"bbox_height":0.947266,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.843750,"charcode":"é","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ê":{"advance_x":0.536621,"bbox_height":0.947754,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.845052,"charcode":"ê","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ë":{"advance_x":0.536621,"bbox_height":0.921875,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.819010,"charcode":"ë","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ì":{"advance_x":0.262695,"bbox_height":0.934082,"bbox_width":0.417969,"bearing_x":-0.131510,"bearing_y":0.841146,"charcode":"ì","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"í":{"advance_x":0.262695,"bbox_height":0.934082,"bbox_width":0.418945,"bearing_x":-0.024740,"bearing_y":0.841146,"charcode":"í","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"î":{"advance_x":0.262695,"bbox_height":0.934570,"bbox_width":0.522949,"bearing_x":-0.130208,"bearing_y":0.841146,"charcode":"î","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ï":{"advance_x":0.262695,"bbox_height":0.908691,"bbox_width":0.534180,"bearing_x":-0.135417,"bearing_y":0.815104,"charcode":"ï","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ð":{"advance_x":0.581543,"bbox_height":0.968750,"bbox_width":0.668457,"bearing_x":-0.044271,"bearing_y":0.865885,"charcode":"ð","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ñ":{"advance_x":0.556152,"bbox_height":0.932617,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.839844,"charcode":"ñ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ò":{"advance_x":0.569336,"bbox_height":0.947266,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ò","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ó":{"advance_x":0.569336,"bbox_height":0.947266,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ó","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ô":{"advance_x":0.569336,"bbox_height":0.947754,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.845052,"charcode":"ô","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"õ":{"advance_x":0.569336,"bbox_height":0.942383,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.839844,"charcode":"õ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ö":{"advance_x":0.569336,"bbox_height":0.921875,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.819010,"charcode":"ö","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"÷":{"advance_x":0.570801,"bbox_height":0.715332,"bbox_width":0.681641,"bearing_x":-0.061198,"bearing_y":0.694010,"charcode":"÷","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ø":{"advance_x":0.566406,"bbox_height":0.845703,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.686198,"charcode":"ø","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ù":{"advance_x":0.555664,"bbox_height":0.947266,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.843750,"charcode":"ù","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ú":{"advance_x":0.555664,"bbox_height":0.947266,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.843750,"charcode":"ú","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"û":{"advance_x":0.555664,"bbox_height":0.947754,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.845052,"charcode":"û","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ü":{"advance_x":0.555664,"bbox_height":0.921875,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.819010,"charcode":"ü","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ý":{"advance_x":0.486816,"bbox_height":1.150879,"bbox_width":0.661133,"bearing_x":-0.088542,"bearing_y":0.843750,"charcode":"ý","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"þ":{"advance_x":0.573730,"bbox_height":1.140625,"bbox_width":0.650879,"bearing_x":-0.031250,"bearing_y":0.843750,"charcode":"þ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ā":{"advance_x":0.665527,"bbox_height":1.048828,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.955729,"charcode":"Ā","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ā":{"advance_x":0.541016,"bbox_height":0.907227,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.804688,"charcode":"ā","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ă":{"advance_x":0.665527,"bbox_height":1.076172,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.983073,"charcode":"Ă","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ă":{"advance_x":0.541016,"bbox_height":0.934570,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.832031,"charcode":"ă","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ą":{"advance_x":0.665527,"bbox_height":1.108398,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.804688,"charcode":"Ą","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ą":{"advance_x":0.541016,"bbox_height":0.935547,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.632812,"charcode":"ą","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ć":{"advance_x":0.652832,"bbox_height":1.108887,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":1.006510,"charcode":"Ć","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ć":{"advance_x":0.523438,"bbox_height":0.947266,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ć","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĉ":{"advance_x":0.652832,"bbox_height":1.109375,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":1.006510,"charcode":"Ĉ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĉ":{"advance_x":0.523438,"bbox_height":0.947754,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.845052,"charcode":"ĉ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ċ":{"advance_x":0.652832,"bbox_height":1.092285,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":0.989583,"charcode":"Ċ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ċ":{"advance_x":0.523438,"bbox_height":0.930664,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.828125,"charcode":"ċ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Č":{"advance_x":0.652832,"bbox_height":1.109375,"bbox_width":0.752441,"bearing_x":-0.044271,"bearing_y":1.006510,"charcode":"Č","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"č":{"advance_x":0.523438,"bbox_height":0.947754,"bbox_width":0.643555,"bearing_x":-0.055990,"bearing_y":0.845052,"charcode":"č","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ď":{"advance_x":0.653320,"bbox_height":1.092773,"bbox_width":0.717773,"bearing_x":-0.022135,"bearing_y":1,"charcode":"Ď","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ď":{"advance_x":0.637695,"bbox_height":0.948242,"bbox_width":0.818359,"bearing_x":-0.055990,"bearing_y":0.845052,"charcode":"ď","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Đ":{"advance_x":0.667969,"bbox_height":0.898438,"bbox_width":0.809082,"bearing_x":-0.098958,"bearing_y":0.804688,"charcode":"Đ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"đ":{"advance_x":0.615723,"bbox_height":0.947266,"bbox_width":0.735840,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"đ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ē":{"advance_x":0.565430,"bbox_height":1.052246,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.959635,"charcode":"Ē","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ē":{"advance_x":0.536621,"bbox_height":0.907227,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.804688,"charcode":"ē","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĕ":{"advance_x":0.565430,"bbox_height":1.079590,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.986979,"charcode":"Ĕ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĕ":{"advance_x":0.536621,"bbox_height":0.934570,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.832031,"charcode":"ĕ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ė":{"advance_x":0.565430,"bbox_height":1.075684,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.983073,"charcode":"Ė","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ė":{"advance_x":0.536621,"bbox_height":0.930664,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.828125,"charcode":"ė","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ę":{"advance_x":0.565430,"bbox_height":1.108398,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ę","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ę":{"advance_x":0.536621,"bbox_height":0.922363,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.632812,"charcode":"ę","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ě":{"advance_x":0.565430,"bbox_height":1.092773,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":1,"charcode":"Ě","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ě":{"advance_x":0.536621,"bbox_height":0.947754,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.845052,"charcode":"ě","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĝ":{"advance_x":0.680664,"bbox_height":1.109375,"bbox_width":0.752930,"bearing_x":-0.042969,"bearing_y":1.006510,"charcode":"Ĝ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĝ":{"advance_x":0.566895,"bbox_height":1.145996,"bbox_width":0.653320,"bearing_x":-0.054688,"bearing_y":0.845052,"charcode":"ĝ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ğ":{"advance_x":0.680664,"bbox_height":1.096191,"bbox_width":0.752930,"bearing_x":-0.042969,"bearing_y":0.993490,"charcode":"Ğ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ğ":{"advance_x":0.566895,"bbox_height":1.132812,"bbox_width":0.653320,"bearing_x":-0.054688,"bearing_y":0.832031,"charcode":"ğ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ġ":{"advance_x":0.680664,"bbox_height":1.092285,"bbox_width":0.752930,"bearing_x":-0.042969,"bearing_y":0.989583,"charcode":"Ġ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ġ":{"advance_x":0.566895,"bbox_height":1.128906,"bbox_width":0.653320,"bearing_x":-0.054688,"bearing_y":0.828125,"charcode":"ġ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ģ":{"advance_x":0.680664,"bbox_height":1.164551,"bbox_width":0.752930,"bearing_x":-0.042969,"bearing_y":0.815104,"charcode":"Ģ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ģ":{"advance_x":0.566895,"bbox_height":1.228027,"bbox_width":0.653320,"bearing_x":-0.054688,"bearing_y":0.927083,"charcode":"ģ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĥ":{"advance_x":0.710449,"bbox_height":1.092773,"bbox_width":0.751953,"bearing_x":-0.022135,"bearing_y":1,"charcode":"Ĥ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĥ":{"advance_x":0.555176,"bbox_height":1.108398,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":1.015625,"charcode":"ĥ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ħ":{"advance_x":0.710938,"bbox_height":0.898438,"bbox_width":0.874023,"bearing_x":-0.079427,"bearing_y":0.804688,"charcode":"Ħ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ħ":{"advance_x":0.569824,"bbox_height":0.937500,"bbox_width":0.719727,"bearing_x":-0.115885,"bearing_y":0.843750,"charcode":"ħ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĩ":{"advance_x":0.282227,"bbox_height":1.087402,"bbox_width":0.545410,"bearing_x":-0.131510,"bearing_y":0.994792,"charcode":"Ĩ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĩ":{"advance_x":0.262695,"bbox_height":0.929199,"bbox_width":0.545410,"bearing_x":-0.141927,"bearing_y":0.835938,"charcode":"ĩ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ī":{"advance_x":0.282227,"bbox_height":1.052246,"bbox_width":0.522949,"bearing_x":-0.119792,"bearing_y":0.959635,"charcode":"Ī","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ī":{"advance_x":0.262695,"bbox_height":0.894043,"bbox_width":0.522949,"bearing_x":-0.128906,"bearing_y":0.800781,"charcode":"ī","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĭ":{"advance_x":0.282227,"bbox_height":1.079590,"bbox_width":0.502930,"bearing_x":-0.110677,"bearing_y":0.986979,"charcode":"Ĭ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĭ":{"advance_x":0.262695,"bbox_height":0.921387,"bbox_width":0.502930,"bearing_x":-0.119792,"bearing_y":0.828125,"charcode":"ĭ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Į":{"advance_x":0.282227,"bbox_height":1.105469,"bbox_width":0.378906,"bearing_x":-0.083333,"bearing_y":0.804688,"charcode":"Į","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"į":{"advance_x":0.255371,"bbox_height":1.126465,"bbox_width":0.382812,"bearing_x":-0.093750,"bearing_y":0.822917,"charcode":"į","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"İ":{"advance_x":0.282227,"bbox_height":1.075684,"bbox_width":0.315430,"bearing_x":-0.018229,"bearing_y":0.983073,"charcode":"İ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ı":{"advance_x":0.262695,"bbox_height":0.715820,"bbox_width":0.306152,"bearing_x":-0.024740,"bearing_y":0.622396,"charcode":"ı","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"IJ":{"advance_x":0.837402,"bbox_height":0.908203,"bbox_width":0.876465,"bearing_x":-0.014323,"bearing_y":0.804688,"charcode":"IJ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ij":{"advance_x":0.505859,"bbox_height":1.129883,"bbox_width":0.571777,"bearing_x":-0.033854,"bearing_y":0.822917,"charcode":"ij","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĵ":{"advance_x":0.555176,"bbox_height":1.099121,"bbox_width":0.749023,"bearing_x":-0.072917,"bearing_y":0.996094,"charcode":"Ĵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĵ":{"advance_x":0.268555,"bbox_height":1.134766,"bbox_width":0.526367,"bearing_x":-0.131510,"bearing_y":0.828125,"charcode":"ĵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ķ":{"advance_x":0.630371,"bbox_height":1.115234,"bbox_width":0.751953,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ķ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ķ":{"advance_x":0.521973,"bbox_height":1.164551,"bbox_width":0.652832,"bearing_x":-0.033854,"bearing_y":0.843750,"charcode":"ķ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĸ":{"advance_x":0.574219,"bbox_height":0.715820,"bbox_width":0.670410,"bearing_x":-0.024740,"bearing_y":0.622396,"charcode":"ĸ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ĺ":{"advance_x":0.541016,"bbox_height":1.088867,"bbox_width":0.633789,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ĺ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ĺ":{"advance_x":0.255371,"bbox_height":1.133301,"bbox_width":0.417969,"bearing_x":-0.027344,"bearing_y":1.040365,"charcode":"ĺ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ļ":{"advance_x":0.541016,"bbox_height":1.146973,"bbox_width":0.633789,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ļ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ļ":{"advance_x":0.255371,"bbox_height":1.186035,"bbox_width":0.333008,"bearing_x":-0.053385,"bearing_y":0.843750,"charcode":"ļ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ľ":{"advance_x":0.541016,"bbox_height":0.898926,"bbox_width":0.633789,"bearing_x":-0.022135,"bearing_y":0.805990,"charcode":"Ľ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ľ":{"advance_x":0.328613,"bbox_height":0.938477,"bbox_width":0.481934,"bearing_x":-0.026042,"bearing_y":0.845052,"charcode":"ľ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŀ":{"advance_x":0.541016,"bbox_height":0.898438,"bbox_width":0.633789,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ŀ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŀ":{"advance_x":0.362793,"bbox_height":0.937500,"bbox_width":0.483887,"bearing_x":-0.026042,"bearing_y":0.843750,"charcode":"ŀ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ł":{"advance_x":0.548828,"bbox_height":0.898438,"bbox_width":0.697266,"bearing_x":-0.078125,"bearing_y":0.804688,"charcode":"Ł","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ł":{"advance_x":0.288574,"bbox_height":0.937500,"bbox_width":0.443848,"bearing_x":-0.078125,"bearing_y":0.843750,"charcode":"ł","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ń":{"advance_x":0.709961,"bbox_height":1.088867,"bbox_width":0.751465,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ń","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ń":{"advance_x":0.556152,"bbox_height":0.937500,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.843750,"charcode":"ń","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ņ":{"advance_x":0.709961,"bbox_height":1.148926,"bbox_width":0.751465,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ņ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ņ":{"advance_x":0.556152,"bbox_height":0.974121,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.632812,"charcode":"ņ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ň":{"advance_x":0.709961,"bbox_height":1.089355,"bbox_width":0.751465,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ň","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ň":{"advance_x":0.556152,"bbox_height":0.937988,"bbox_width":0.624512,"bearing_x":-0.035156,"bearing_y":0.845052,"charcode":"ň","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ʼn":{"advance_x":0.556152,"bbox_height":0.938965,"bbox_width":0.728027,"bearing_x":-0.139323,"bearing_y":0.846354,"charcode":"ʼn","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŋ":{"advance_x":0.696777,"bbox_height":1.111816,"bbox_width":0.746582,"bearing_x":-0.023438,"bearing_y":0.804688,"charcode":"Ŋ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŋ":{"advance_x":0.566406,"bbox_height":0.938965,"bbox_width":0.628906,"bearing_x":-0.032552,"bearing_y":0.632812,"charcode":"ŋ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ō":{"advance_x":0.690430,"bbox_height":1.058594,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.955729,"charcode":"Ō","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ō":{"advance_x":0.569336,"bbox_height":0.907227,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.804688,"charcode":"ō","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŏ":{"advance_x":0.690430,"bbox_height":1.085938,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.983073,"charcode":"Ŏ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŏ":{"advance_x":0.569336,"bbox_height":0.934570,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.832031,"charcode":"ŏ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ő":{"advance_x":0.690430,"bbox_height":1.098145,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.994792,"charcode":"Ő","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ő":{"advance_x":0.569336,"bbox_height":0.946777,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ő","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Œ":{"advance_x":0.962891,"bbox_height":0.917969,"bbox_width":1.035645,"bearing_x":-0.045573,"bearing_y":0.815104,"charcode":"Œ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"œ":{"advance_x":0.903320,"bbox_height":0.735840,"bbox_width":1.011230,"bearing_x":-0.049479,"bearing_y":0.632812,"charcode":"œ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŕ":{"advance_x":0.624023,"bbox_height":1.088867,"bbox_width":0.723633,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ŕ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŕ":{"advance_x":0.351562,"bbox_height":0.937500,"bbox_width":0.496582,"bearing_x":-0.033854,"bearing_y":0.843750,"charcode":"ŕ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŗ":{"advance_x":0.624023,"bbox_height":1.146973,"bbox_width":0.723633,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ŗ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŗ":{"advance_x":0.351562,"bbox_height":0.974121,"bbox_width":0.486816,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"ŗ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ř":{"advance_x":0.624023,"bbox_height":1.089355,"bbox_width":0.723633,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ř","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ř":{"advance_x":0.351562,"bbox_height":0.937988,"bbox_width":0.532227,"bearing_x":-0.066406,"bearing_y":0.845052,"charcode":"ř","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ś":{"advance_x":0.603516,"bbox_height":1.098633,"bbox_width":0.718750,"bearing_x":-0.058594,"bearing_y":0.996094,"charcode":"Ś","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ś":{"advance_x":0.516113,"bbox_height":0.947266,"bbox_width":0.624512,"bearing_x":-0.057292,"bearing_y":0.843750,"charcode":"ś","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŝ":{"advance_x":0.603516,"bbox_height":1.099121,"bbox_width":0.718750,"bearing_x":-0.058594,"bearing_y":0.996094,"charcode":"Ŝ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŝ":{"advance_x":0.516113,"bbox_height":0.947754,"bbox_width":0.624512,"bearing_x":-0.057292,"bearing_y":0.845052,"charcode":"ŝ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ş":{"advance_x":0.603516,"bbox_height":1.126465,"bbox_width":0.718750,"bearing_x":-0.058594,"bearing_y":0.815104,"charcode":"Ş","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ş":{"advance_x":0.516113,"bbox_height":0.948242,"bbox_width":0.624512,"bearing_x":-0.057292,"bearing_y":0.632812,"charcode":"ş","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Š":{"advance_x":0.603516,"bbox_height":1.099121,"bbox_width":0.718750,"bearing_x":-0.058594,"bearing_y":0.996094,"charcode":"Š","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"š":{"advance_x":0.516113,"bbox_height":0.947754,"bbox_width":0.624512,"bearing_x":-0.057292,"bearing_y":0.845052,"charcode":"š","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ţ":{"advance_x":0.606934,"bbox_height":1.115234,"bbox_width":0.751465,"bearing_x":-0.072917,"bearing_y":0.804688,"charcode":"Ţ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ţ":{"advance_x":0.332520,"bbox_height":1.062500,"bbox_width":0.514160,"bearing_x":-0.089844,"bearing_y":0.751302,"charcode":"ţ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ť":{"advance_x":0.606934,"bbox_height":1.089355,"bbox_width":0.751465,"bearing_x":-0.072917,"bearing_y":0.996094,"charcode":"Ť","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ť":{"advance_x":0.352051,"bbox_height":1.011230,"bbox_width":0.577637,"bearing_x":-0.089844,"bearing_y":0.908854,"charcode":"ť","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŧ":{"advance_x":0.606934,"bbox_height":0.898438,"bbox_width":0.751465,"bearing_x":-0.072917,"bearing_y":0.804688,"charcode":"Ŧ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŧ":{"advance_x":0.332520,"bbox_height":0.854004,"bbox_width":0.514160,"bearing_x":-0.105469,"bearing_y":0.751302,"charcode":"ŧ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ũ":{"advance_x":0.651855,"bbox_height":1.093750,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.990885,"charcode":"Ũ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ũ":{"advance_x":0.555664,"bbox_height":0.942383,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.839844,"charcode":"ũ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ū":{"advance_x":0.651855,"bbox_height":1.058594,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.955729,"charcode":"Ū","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ū":{"advance_x":0.555664,"bbox_height":0.907227,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.804688,"charcode":"ū","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŭ":{"advance_x":0.651855,"bbox_height":1.085938,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.983073,"charcode":"Ŭ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŭ":{"advance_x":0.555664,"bbox_height":0.934570,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.832031,"charcode":"ŭ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ů":{"advance_x":0.651855,"bbox_height":1.144531,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":1.041667,"charcode":"Ů","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ů":{"advance_x":0.555664,"bbox_height":0.993164,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.890625,"charcode":"ů","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ű":{"advance_x":0.651855,"bbox_height":1.098145,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.994792,"charcode":"Ű","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ű":{"advance_x":0.555664,"bbox_height":0.946777,"bbox_width":0.651855,"bearing_x":-0.036458,"bearing_y":0.843750,"charcode":"ű","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ų":{"advance_x":0.651855,"bbox_height":1.081543,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.804688,"charcode":"Ų","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ų":{"advance_x":0.555664,"bbox_height":0.925781,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.622396,"charcode":"ų","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŵ":{"advance_x":0.879883,"bbox_height":1.089355,"bbox_width":1.025879,"bearing_x":-0.070312,"bearing_y":0.996094,"charcode":"Ŵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŵ":{"advance_x":0.743164,"bbox_height":0.937988,"bbox_width":0.895996,"bearing_x":-0.078125,"bearing_y":0.845052,"charcode":"ŵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ŷ":{"advance_x":0.609375,"bbox_height":1.089355,"bbox_width":0.788574,"bearing_x":-0.091146,"bearing_y":0.996094,"charcode":"Ŷ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ŷ":{"advance_x":0.486816,"bbox_height":1.151367,"bbox_width":0.661133,"bearing_x":-0.088542,"bearing_y":0.845052,"charcode":"ŷ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ÿ":{"advance_x":0.609375,"bbox_height":1.063477,"bbox_width":0.788574,"bearing_x":-0.091146,"bearing_y":0.970052,"charcode":"Ÿ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ź":{"advance_x":0.602051,"bbox_height":1.088867,"bbox_width":0.716797,"bearing_x":-0.054688,"bearing_y":0.996094,"charcode":"Ź","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ź":{"advance_x":0.502930,"bbox_height":0.937500,"bbox_width":0.616211,"bearing_x":-0.054688,"bearing_y":0.843750,"charcode":"ź","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ż":{"advance_x":0.602051,"bbox_height":1.072266,"bbox_width":0.716797,"bearing_x":-0.054688,"bearing_y":0.979167,"charcode":"Ż","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ż":{"advance_x":0.502930,"bbox_height":0.920898,"bbox_width":0.616211,"bearing_x":-0.054688,"bearing_y":0.828125,"charcode":"ż","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ž":{"advance_x":0.602051,"bbox_height":1.089355,"bbox_width":0.716797,"bearing_x":-0.054688,"bearing_y":0.996094,"charcode":"Ž","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ž":{"advance_x":0.502930,"bbox_height":0.937988,"bbox_width":0.616211,"bearing_x":-0.054688,"bearing_y":0.845052,"charcode":"ž","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ḿ":{"advance_x":0.875488,"bbox_height":1.088867,"bbox_width":0.916992,"bearing_x":-0.022135,"bearing_y":0.996094,"charcode":"Ḿ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ḿ":{"advance_x":0.870117,"bbox_height":0.937500,"bbox_width":0.936035,"bearing_x":-0.033854,"bearing_y":0.843750,"charcode":"ḿ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẁ":{"advance_x":0.879883,"bbox_height":1.088867,"bbox_width":1.025879,"bearing_x":-0.070312,"bearing_y":0.996094,"charcode":"Ẁ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẁ":{"advance_x":0.743164,"bbox_height":0.937500,"bbox_width":0.895996,"bearing_x":-0.078125,"bearing_y":0.843750,"charcode":"ẁ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẃ":{"advance_x":0.879883,"bbox_height":1.088867,"bbox_width":1.025879,"bearing_x":-0.070312,"bearing_y":0.996094,"charcode":"Ẃ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẃ":{"advance_x":0.743164,"bbox_height":0.937500,"bbox_width":0.895996,"bearing_x":-0.078125,"bearing_y":0.843750,"charcode":"ẃ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẅ":{"advance_x":0.879883,"bbox_height":1.063477,"bbox_width":1.025879,"bearing_x":-0.070312,"bearing_y":0.970052,"charcode":"Ẅ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẅ":{"advance_x":0.743164,"bbox_height":0.912109,"bbox_width":0.895996,"bearing_x":-0.078125,"bearing_y":0.819010,"charcode":"ẅ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ạ":{"advance_x":0.665527,"bbox_height":1.074707,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.804688,"charcode":"Ạ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ạ":{"advance_x":0.541016,"bbox_height":0.899902,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.632812,"charcode":"ạ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ả":{"advance_x":0.665527,"bbox_height":1.153809,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.061198,"charcode":"Ả","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ả":{"advance_x":0.541016,"bbox_height":1.012207,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.908854,"charcode":"ả","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ấ":{"advance_x":0.665527,"bbox_height":1.148926,"bbox_width":0.839844,"bearing_x":-0.085938,"bearing_y":1.055990,"charcode":"Ấ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ấ":{"advance_x":0.541016,"bbox_height":1.007812,"bbox_width":0.747070,"bearing_x":-0.050781,"bearing_y":0.904948,"charcode":"ấ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ầ":{"advance_x":0.665527,"bbox_height":1.147461,"bbox_width":0.836914,"bearing_x":-0.085938,"bearing_y":1.054688,"charcode":"Ầ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ầ":{"advance_x":0.541016,"bbox_height":1.006348,"bbox_width":0.734863,"bearing_x":-0.144531,"bearing_y":0.903646,"charcode":"ầ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẩ":{"advance_x":0.665527,"bbox_height":1.170898,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.078125,"charcode":"Ẩ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẩ":{"advance_x":0.541016,"bbox_height":1.029785,"bbox_width":0.686035,"bearing_x":-0.050781,"bearing_y":0.927083,"charcode":"ẩ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẫ":{"advance_x":0.665527,"bbox_height":1.166992,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.074219,"charcode":"Ẫ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẫ":{"advance_x":0.541016,"bbox_height":1.025879,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.923177,"charcode":"ẫ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ậ":{"advance_x":0.665527,"bbox_height":1.265625,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.996094,"charcode":"Ậ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ậ":{"advance_x":0.541016,"bbox_height":1.112305,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.845052,"charcode":"ậ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ắ":{"advance_x":0.665527,"bbox_height":1.147461,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.054688,"charcode":"Ắ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ắ":{"advance_x":0.541016,"bbox_height":1.006348,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.903646,"charcode":"ắ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ằ":{"advance_x":0.665527,"bbox_height":1.147461,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.054688,"charcode":"Ằ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ằ":{"advance_x":0.541016,"bbox_height":1.006348,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.903646,"charcode":"ằ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẳ":{"advance_x":0.665527,"bbox_height":1.217773,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.125000,"charcode":"Ẳ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẳ":{"advance_x":0.541016,"bbox_height":1.076172,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.972656,"charcode":"ẳ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẵ":{"advance_x":0.665527,"bbox_height":1.199219,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":1.105469,"charcode":"Ẵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẵ":{"advance_x":0.541016,"bbox_height":1.057617,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.954427,"charcode":"ẵ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ặ":{"advance_x":0.665527,"bbox_height":1.252441,"bbox_width":0.835938,"bearing_x":-0.085938,"bearing_y":0.983073,"charcode":"Ặ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ặ":{"advance_x":0.541016,"bbox_height":1.099121,"bbox_width":0.641113,"bearing_x":-0.050781,"bearing_y":0.832031,"charcode":"ặ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẹ":{"advance_x":0.565430,"bbox_height":1.071289,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ẹ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẹ":{"advance_x":0.536621,"bbox_height":0.903320,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.632812,"charcode":"ẹ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẻ":{"advance_x":0.565430,"bbox_height":1.157227,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":1.063802,"charcode":"Ẻ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẻ":{"advance_x":0.536621,"bbox_height":1.012207,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.908854,"charcode":"ẻ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ẽ":{"advance_x":0.565430,"bbox_height":1.087402,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":0.994792,"charcode":"Ẽ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ẽ":{"advance_x":0.536621,"bbox_height":0.942383,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.839844,"charcode":"ẽ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ế":{"advance_x":0.565430,"bbox_height":1.152344,"bbox_width":0.747559,"bearing_x":-0.022135,"bearing_y":1.058594,"charcode":"Ế","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ế":{"advance_x":0.536621,"bbox_height":1.007812,"bbox_width":0.744629,"bearing_x":-0.053385,"bearing_y":0.904948,"charcode":"ế","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ề":{"advance_x":0.565430,"bbox_height":1.150879,"bbox_width":0.745605,"bearing_x":-0.115885,"bearing_y":1.057292,"charcode":"Ề","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ề":{"advance_x":0.536621,"bbox_height":1.006348,"bbox_width":0.748535,"bearing_x":-0.149740,"bearing_y":0.903646,"charcode":"ề","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ể":{"advance_x":0.565430,"bbox_height":1.174316,"bbox_width":0.686523,"bearing_x":-0.022135,"bearing_y":1.080729,"charcode":"Ể","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ể":{"advance_x":0.536621,"bbox_height":1.029785,"bbox_width":0.683594,"bearing_x":-0.053385,"bearing_y":0.927083,"charcode":"ể","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ễ":{"advance_x":0.565430,"bbox_height":1.170410,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":1.076823,"charcode":"Ễ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ễ":{"advance_x":0.536621,"bbox_height":1.025879,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.923177,"charcode":"ễ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ệ":{"advance_x":0.565430,"bbox_height":1.265625,"bbox_width":0.652344,"bearing_x":-0.022135,"bearing_y":1,"charcode":"Ệ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ệ":{"advance_x":0.536621,"bbox_height":1.115723,"bbox_width":0.652344,"bearing_x":-0.053385,"bearing_y":0.845052,"charcode":"ệ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ỉ":{"advance_x":0.282227,"bbox_height":1.157227,"bbox_width":0.366211,"bearing_x":-0.014323,"bearing_y":1.063802,"charcode":"Ỉ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ỉ":{"advance_x":0.262695,"bbox_height":0.999023,"bbox_width":0.366211,"bearing_x":-0.024740,"bearing_y":0.906250,"charcode":"ỉ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ị":{"advance_x":0.282227,"bbox_height":1.073242,"bbox_width":0.321777,"bearing_x":-0.022135,"bearing_y":0.804688,"charcode":"Ị","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ị":{"advance_x":0.255371,"bbox_height":1.089355,"bbox_width":0.324219,"bearing_x":-0.035156,"bearing_y":0.822917,"charcode":"ị","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ọ":{"advance_x":0.690430,"bbox_height":1.085938,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.815104,"charcode":"Ọ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ọ":{"advance_x":0.569336,"bbox_height":0.904297,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.632812,"charcode":"ọ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ỏ":{"advance_x":0.690430,"bbox_height":1.163574,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":1.061198,"charcode":"Ỏ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ỏ":{"advance_x":0.569336,"bbox_height":1.012207,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.908854,"charcode":"ỏ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ố":{"advance_x":0.690430,"bbox_height":1.158691,"bbox_width":0.810059,"bearing_x":-0.044271,"bearing_y":1.055990,"charcode":"Ố","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ố":{"advance_x":0.569336,"bbox_height":1.007812,"bbox_width":0.756836,"bearing_x":-0.055990,"bearing_y":0.904948,"charcode":"ố","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ồ":{"advance_x":0.690430,"bbox_height":1.157227,"bbox_width":0.808105,"bearing_x":-0.075521,"bearing_y":1.054688,"charcode":"Ồ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ồ":{"advance_x":0.569336,"bbox_height":1.006348,"bbox_width":0.762695,"bearing_x":-0.139323,"bearing_y":0.903646,"charcode":"ồ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ổ":{"advance_x":0.690430,"bbox_height":1.180664,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":1.078125,"charcode":"Ổ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ổ":{"advance_x":0.569336,"bbox_height":1.029785,"bbox_width":0.695801,"bearing_x":-0.055990,"bearing_y":0.927083,"charcode":"ổ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ỗ":{"advance_x":0.690430,"bbox_height":1.176758,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":1.074219,"charcode":"Ỗ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ỗ":{"advance_x":0.569336,"bbox_height":1.025879,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.923177,"charcode":"ỗ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ộ":{"advance_x":0.690430,"bbox_height":1.267090,"bbox_width":0.777344,"bearing_x":-0.044271,"bearing_y":0.996094,"charcode":"Ộ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ộ":{"advance_x":0.569336,"bbox_height":1.116699,"bbox_width":0.678711,"bearing_x":-0.055990,"bearing_y":0.845052,"charcode":"ộ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ớ":{"advance_x":0.692383,"bbox_height":1.097168,"bbox_width":0.852539,"bearing_x":-0.050781,"bearing_y":0.994792,"charcode":"Ớ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ớ":{"advance_x":0.577148,"bbox_height":0.947266,"bbox_width":0.740234,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ớ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ờ":{"advance_x":0.692383,"bbox_height":1.097168,"bbox_width":0.852539,"bearing_x":-0.050781,"bearing_y":0.994792,"charcode":"Ờ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ờ":{"advance_x":0.577148,"bbox_height":0.947266,"bbox_width":0.740234,"bearing_x":-0.055990,"bearing_y":0.843750,"charcode":"ờ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ở":{"advance_x":0.692383,"bbox_height":1.162109,"bbox_width":0.852539,"bearing_x":-0.050781,"bearing_y":1.058594,"charcode":"Ở","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ở":{"advance_x":0.577148,"bbox_height":1.012207,"bbox_width":0.740234,"bearing_x":-0.055990,"bearing_y":0.908854,"charcode":"ở","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ỡ":{"advance_x":0.692383,"bbox_height":1.092285,"bbox_width":0.852539,"bearing_x":-0.050781,"bearing_y":0.989583,"charcode":"Ỡ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ỡ":{"advance_x":0.577148,"bbox_height":0.942383,"bbox_width":0.740234,"bearing_x":-0.055990,"bearing_y":0.839844,"charcode":"ỡ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ợ":{"advance_x":0.692383,"bbox_height":1.137695,"bbox_width":0.852539,"bearing_x":-0.050781,"bearing_y":0.867188,"charcode":"Ợ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ợ":{"advance_x":0.577148,"bbox_height":0.951660,"bbox_width":0.740234,"bearing_x":-0.055990,"bearing_y":0.675781,"charcode":"ợ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ụ":{"advance_x":0.651855,"bbox_height":1.076172,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":0.804688,"charcode":"Ụ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ụ":{"advance_x":0.555664,"bbox_height":0.893555,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.622396,"charcode":"ụ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ủ":{"advance_x":0.651855,"bbox_height":1.163574,"bbox_width":0.718750,"bearing_x":-0.033854,"bearing_y":1.061198,"charcode":"Ủ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ủ":{"advance_x":0.555664,"bbox_height":1.012207,"bbox_width":0.625000,"bearing_x":-0.036458,"bearing_y":0.908854,"charcode":"ủ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ứ":{"advance_x":0.705078,"bbox_height":1.104492,"bbox_width":0.906250,"bearing_x":-0.033854,"bearing_y":1.001302,"charcode":"Ứ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ứ":{"advance_x":0.618164,"bbox_height":0.937500,"bbox_width":0.773926,"bearing_x":-0.036458,"bearing_y":0.834635,"charcode":"ứ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ừ":{"advance_x":0.705078,"bbox_height":1.104492,"bbox_width":0.906250,"bearing_x":-0.033854,"bearing_y":1.001302,"charcode":"Ừ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ừ":{"advance_x":0.618164,"bbox_height":0.937500,"bbox_width":0.773926,"bearing_x":-0.036458,"bearing_y":0.834635,"charcode":"ừ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ử":{"advance_x":0.705078,"bbox_height":1.169434,"bbox_width":0.906250,"bearing_x":-0.033854,"bearing_y":1.066406,"charcode":"Ử","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ử":{"advance_x":0.618164,"bbox_height":1.002441,"bbox_width":0.773926,"bearing_x":-0.036458,"bearing_y":0.899740,"charcode":"ử","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ữ":{"advance_x":0.705078,"bbox_height":1.099609,"bbox_width":0.906250,"bearing_x":-0.033854,"bearing_y":0.996094,"charcode":"Ữ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ữ":{"advance_x":0.618164,"bbox_height":0.932617,"bbox_width":0.773926,"bearing_x":-0.036458,"bearing_y":0.829427,"charcode":"ữ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ự":{"advance_x":0.705078,"bbox_height":1.120117,"bbox_width":0.906250,"bearing_x":-0.033854,"bearing_y":0.845052,"charcode":"Ự","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"ự":{"advance_x":0.618164,"bbox_height":0.937012,"bbox_width":0.773926,"bearing_x":-0.036458,"bearing_y":0.666667,"charcode":"ự","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0},"Ỳ":{"advance_x":0.609375,"bbox_height":1.088867,"bbox_width":0.788574,"bearing_x":-0.091146,"bearing_y":0.996094,"charcode":"Ỳ","kernings":{},"s0":0,"s1":0,"t0":0,"t1":0}},"height":1.177083,"max_advance":1.177083,"name":"Roboto-Medium","size":96,"space_advance":0.249023} -------------------------------------------------------------------------------- /Fonts/Roboto-Medium.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shipyard-games/SCNText2D/88f0b4da36072e6a9537b88eab54df9b5f3893cb/Fonts/Roboto-Medium.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Shipyard Games Oy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SCNText2D 2 | 3 | Rendering text in SceneKit using SDF fonts. 4 | 5 | ### Features 6 | 7 | Currently this framework uses a pre-generated font texture atlas to render 2D text in SceneKit scene. It creates a `SCNGeometry` and configures a material for it for rendering. More examples and features coming in the future. Try out the framework with the included test applications for iOS and macOS. 8 | 9 | ### TODO 10 | 11 | - [x] Take out the font files from the framework and write instructions on including them manually. They grow the binary size of the framework. 12 | - [x] Implement text alignment. Currently text is always left aligned. 13 | - [ ] Add support for tvOS. 14 | - [ ] Figure out what to implement for the v1.0. 15 | 16 | ### Installing using Carthage 17 | 18 | Add this line to your `Cartfile`. 19 | 20 | ``` 21 | github "shipyard-games/SCNText2D" "v0.1.0" 22 | ``` 23 | 24 | ### Running the test applications 25 | 26 | The project comes with test applications for iOS and macOS. You can simply run them from Xcode. 27 | 28 | ![Example](https://pbs.twimg.com/media/D3sU9ZUX4AIvqYn.jpg:large) 29 | -------------------------------------------------------------------------------- /SCNText2D-Shaders-iOS/SDFText.metal: -------------------------------------------------------------------------------- 1 | // 2 | // SDFText.metal 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | #include 9 | using namespace metal; 10 | 11 | #include 12 | 13 | typedef struct { 14 | float4 position [[ attribute(SCNVertexSemanticPosition) ]]; 15 | float2 uv [[ attribute(SCNVertexSemanticTexcoord0) ]]; 16 | } input_t; 17 | 18 | typedef struct { 19 | float4x4 modelViewProjectionTransform; 20 | } node_t; 21 | 22 | typedef struct { 23 | float4 position [[ position ]]; 24 | float2 uv; 25 | } io_t; 26 | 27 | typedef struct { 28 | float smoothing; 29 | float fontWidth; 30 | float outlineWidth; 31 | float shadowWidth; 32 | float2 shadowOffset; 33 | float4 fontColor; 34 | float4 outlineColor; 35 | float4 shadowColor; 36 | } params_t; 37 | 38 | vertex io_t sdfTextVertex(input_t in [[ stage_in ]], 39 | constant SCNSceneBuffer& scn_frame [[ buffer(0) ]], 40 | constant node_t& scn_node [[ buffer(1) ]]) { 41 | io_t out; 42 | out.position = scn_node.modelViewProjectionTransform * in.position; 43 | out.uv = in.uv; 44 | 45 | return out; 46 | } 47 | 48 | constexpr sampler s(coord::normalized, address::clamp_to_zero, filter::linear); 49 | 50 | fragment half4 sdfTextFragment(io_t in [[ stage_in ]], 51 | texture2d fontTexture [[ texture(0) ]], 52 | constant params_t& params [[ buffer(1) ]]) { 53 | 54 | float4 distanceVec = fontTexture.sample(s, in.uv); 55 | float distance = length(distanceVec.rgb); 56 | float finalColor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 57 | 58 | return half4(finalColor); 59 | } 60 | 61 | fragment half4 sdfTextOutlineFragment(io_t in [[ stage_in ]], 62 | texture2d fontTexture [[ texture(0) ]], 63 | constant params_t& params [[ buffer(1) ]]) { 64 | 65 | float4 distanceVec = fontTexture.sample(s, in.uv); 66 | float distance = length(distanceVec.rgb); 67 | float outlineFactor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 68 | float4 color = mix(params.outlineColor, params.fontColor, outlineFactor); 69 | float alpha = smoothstep(params.outlineWidth - params.smoothing, params.outlineWidth + params.smoothing, distance); 70 | float4 finalColor = float4(color.rgb * alpha, color.a * alpha); 71 | 72 | return half4(finalColor); 73 | } 74 | 75 | fragment half4 sdfTextOutlineShadowFragment(io_t in [[ stage_in ]], 76 | texture2d fontTexture [[ texture(0) ]], 77 | constant params_t& params [[ buffer(1) ]]) { 78 | 79 | float4 distanceVec = fontTexture.sample(s, in.uv); 80 | float distance = length(distanceVec.rgb); 81 | float outlineFactor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 82 | float4 color = mix(params.outlineColor, params.fontColor, outlineFactor); 83 | float alpha = smoothstep(params.outlineWidth - params.smoothing, params.outlineWidth + params.smoothing, distance); 84 | float4 colorWithOutline = float4(color.rgb * alpha, color.a * alpha); 85 | float4 shadowDistanceVec = fontTexture.sample(s, in.uv - params.shadowOffset); 86 | float shadowDistance = length(shadowDistanceVec.rgb); 87 | float shadowAlpha = smoothstep(params.shadowWidth - params.smoothing, params.shadowWidth + params.smoothing, shadowDistance); 88 | float4 shadow = float4(params.shadowColor.rgb * shadowAlpha, params.shadowColor.a * shadowAlpha); 89 | float4 finalColor = mix(shadow, colorWithOutline, smoothstep(0.8, 1.0, colorWithOutline.a)); 90 | 91 | return half4(finalColor); 92 | } 93 | -------------------------------------------------------------------------------- /SCNText2D-Shaders-macOS/SDFText.metal: -------------------------------------------------------------------------------- 1 | // 2 | // SDFText.metal 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | #include 9 | using namespace metal; 10 | 11 | #include 12 | 13 | typedef struct { 14 | float4 position [[ attribute(SCNVertexSemanticPosition) ]]; 15 | float2 uv [[ attribute(SCNVertexSemanticTexcoord0) ]]; 16 | } input_t; 17 | 18 | typedef struct { 19 | float4x4 modelViewProjectionTransform; 20 | } node_t; 21 | 22 | typedef struct { 23 | float4 position [[ position ]]; 24 | float2 uv; 25 | } io_t; 26 | 27 | typedef struct { 28 | float smoothing; 29 | float fontWidth; 30 | float outlineWidth; 31 | float shadowWidth; 32 | float2 shadowOffset; 33 | float4 fontColor; 34 | float4 outlineColor; 35 | float4 shadowColor; 36 | } params_t; 37 | 38 | vertex io_t sdfTextVertex(input_t in [[ stage_in ]], 39 | constant SCNSceneBuffer& scn_frame [[ buffer(0) ]], 40 | constant node_t& scn_node [[ buffer(1) ]]) { 41 | io_t out; 42 | out.position = scn_node.modelViewProjectionTransform * in.position; 43 | out.uv = in.uv; 44 | 45 | return out; 46 | } 47 | 48 | constexpr sampler s(coord::normalized, address::clamp_to_zero, filter::linear); 49 | 50 | fragment half4 sdfTextFragment(io_t in [[ stage_in ]], 51 | texture2d fontTexture [[ texture(0) ]], 52 | constant params_t& params [[ buffer(1) ]]) { 53 | 54 | float4 distanceVec = fontTexture.sample(s, in.uv); 55 | float distance = length(distanceVec.rgb); 56 | float finalColor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 57 | 58 | return half4(finalColor); 59 | } 60 | 61 | fragment half4 sdfTextOutlineFragment(io_t in [[ stage_in ]], 62 | texture2d fontTexture [[ texture(0) ]], 63 | constant params_t& params [[ buffer(1) ]]) { 64 | 65 | float4 distanceVec = fontTexture.sample(s, in.uv); 66 | float distance = length(distanceVec.rgb); 67 | float outlineFactor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 68 | float4 color = mix(params.outlineColor, params.fontColor, outlineFactor); 69 | float alpha = smoothstep(params.outlineWidth - params.smoothing, params.outlineWidth + params.smoothing, distance); 70 | float4 finalColor = float4(color.rgb * alpha, color.a * alpha); 71 | 72 | return half4(finalColor); 73 | } 74 | 75 | fragment half4 sdfTextOutlineShadowFragment(io_t in [[ stage_in ]], 76 | texture2d fontTexture [[ texture(0) ]], 77 | constant params_t& params [[ buffer(1) ]]) { 78 | 79 | float4 distanceVec = fontTexture.sample(s, in.uv); 80 | float distance = length(distanceVec.rgb); 81 | float outlineFactor = smoothstep(params.fontWidth - params.smoothing, params.fontWidth + params.smoothing, distance); 82 | float4 color = mix(params.outlineColor, params.fontColor, outlineFactor); 83 | float alpha = smoothstep(params.outlineWidth - params.smoothing, params.outlineWidth + params.smoothing, distance); 84 | float4 colorWithOutline = float4(color.rgb * alpha, color.a * alpha); 85 | float4 shadowDistanceVec = fontTexture.sample(s, in.uv - params.shadowOffset); 86 | float shadowDistance = length(shadowDistanceVec.rgb); 87 | float shadowAlpha = smoothstep(params.shadowWidth - params.smoothing, params.shadowWidth + params.smoothing, shadowDistance); 88 | float4 shadow = float4(params.shadowColor.rgb * shadowAlpha, params.shadowColor.a * shadowAlpha); 89 | float4 finalColor = mix(shadow, colorWithOutline, smoothstep(0.8, 1.0, colorWithOutline.a)); 90 | 91 | return half4(finalColor); 92 | } 93 | -------------------------------------------------------------------------------- /SCNText2D-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNText2D-iOS/SCNText2D_iOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCNText2D_iOS.h 3 | // SCNText2D-iOS 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for SCNText2D_iOS. 11 | FOUNDATION_EXPORT double SCNText2D_iOSVersionNumber; 12 | 13 | //! Project version string for SCNText2D_iOS. 14 | FOUNDATION_EXPORT const unsigned char SCNText2D_iOSVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SCNText2D-iOSTestApp 4 | // 5 | // Created by Teemu Harju on 12/02/2019. 6 | // 7 | 8 | import UIKit 9 | 10 | @UIApplicationMain 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // SCNText2D-iOSTestApp 4 | // 5 | // Created by Teemu Harju on 12/02/2019. 6 | // 7 | 8 | import UIKit 9 | import QuartzCore 10 | import SceneKit 11 | import SCNText2D 12 | 13 | class GameViewController: UIViewController { 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | // create a new scene 19 | let scene = SCNScene() 20 | 21 | // create and add a camera to the scene 22 | let cameraNode = SCNNode() 23 | cameraNode.camera = SCNCamera() 24 | scene.rootNode.addChildNode(cameraNode) 25 | 26 | // place the camera 27 | cameraNode.position = SCNVector3(x: 0, y: 0, z: 15) 28 | 29 | // create and add a light to the scene 30 | let lightNode = SCNNode() 31 | lightNode.light = SCNLight() 32 | lightNode.light!.type = .omni 33 | lightNode.position = SCNVector3(x: 0, y: 10, z: 10) 34 | scene.rootNode.addChildNode(lightNode) 35 | 36 | // create and add an ambient light to the scene 37 | let ambientLightNode = SCNNode() 38 | ambientLightNode.light = SCNLight() 39 | ambientLightNode.light!.type = .ambient 40 | ambientLightNode.light!.color = UIColor.darkGray 41 | scene.rootNode.addChildNode(ambientLightNode) 42 | 43 | // retrieve the SCNView 44 | let scnView = self.view as! SCNView 45 | 46 | // set the scene to the view 47 | scnView.scene = scene 48 | 49 | // allows the user to manipulate the camera 50 | scnView.allowsCameraControl = true 51 | 52 | // show statistics such as fps and timing information 53 | scnView.showsStatistics = true 54 | 55 | // configure the view 56 | scnView.backgroundColor = UIColor(displayP3Red: 3/255, green: 3/255.0, blue: 3/255.0, alpha: 1.0) 57 | 58 | let text = 59 | """ 60 | It is a period of civil war. 61 | Rebel spaceships, striking 62 | from a hidden base, have won 63 | their first victory against 64 | the evil Galactic Empire. 65 | 66 | During the battle, Rebel 67 | spies managed to steal secret 68 | plans to the Empire's 69 | ultimate weapon, the DEATH 70 | STAR, an armored space 71 | station with enough power to 72 | destroy an entire planet. 73 | 74 | Pursued by the Empire's 75 | sinister agents, Princess 76 | Leia races home aboard her 77 | starship, custodian of the 78 | stolen plans that can save 79 | her people and restore 80 | freedom to the galaxy..... 81 | """ 82 | 83 | let fontConfig = SCNText2D.SDFParams( 84 | smoothing: 0.1, 85 | fontWidth: 0.9, 86 | outlineWidth: 0.5, 87 | shadowWidth: 0.5, 88 | shadowOffset: float2(0.0, 0.0), 89 | fontColor: float4(0.0, 0.0, 0.0, 1.0), 90 | outlineColor: float4(1.0, 1.0, 0.0, 1.0), 91 | shadowColor: float4(0.0, 0.0, 0.0, 0.0) 92 | ) 93 | 94 | SCNText2D.load(font: "OpenSans-Regular", bundle: Bundle.main, fontConfig: fontConfig) 95 | 96 | let textGeometry = SCNText2D.create(from: text, 97 | withFontNamed: "OpenSans-Regular", 98 | alignment: .centered) 99 | 100 | let node = SCNNode() 101 | node.eulerAngles.x += -35.0 * (180.0 / .pi) 102 | 103 | 104 | let textNode = SCNNode() 105 | textNode.geometry = textGeometry 106 | 107 | let moveAction = SCNAction.move(by: SCNVector3(x:0, y: 200.0, z: 0.0), duration: 240.0) 108 | textNode.runAction(moveAction) 109 | node.addChildNode(textNode) 110 | 111 | scene.rootNode.addChildNode(node) 112 | } 113 | 114 | override var shouldAutorotate: Bool { 115 | return true 116 | } 117 | 118 | override var prefersStatusBarHidden: Bool { 119 | return true 120 | } 121 | 122 | override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 123 | if UIDevice.current.userInterfaceIdiom == .phone { 124 | return .allButUpsideDown 125 | } else { 126 | return .all 127 | } 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /SCNText2D-iOSTestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | UISupportedInterfaceOrientations~ipad 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /SCNText2D-iOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNText2D-iOSTests/SCNText2D_iOSTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNText2D_iOSTests.swift 3 | // SCNText2D-iOSTests 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import XCTest 9 | @testable import SCNText2D_iOS 10 | 11 | class SCNText2D_iOSTests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDown() { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | func testPerformanceExample() { 27 | // This is an example of a performance test case. 28 | self.measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /SCNText2D-macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNText2D-macOS/SCNText2D_macOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // SCNText2D_macOS.h 3 | // SCNText2D-macOS 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | #import 9 | 10 | //! Project version number for SCNText2D_macOS. 11 | FOUNDATION_EXPORT double SCNText2D_macOSVersionNumber; 12 | 13 | //! Project version string for SCNText2D_macOS. 14 | FOUNDATION_EXPORT const unsigned char SCNText2D_macOSVersionString[]; 15 | 16 | // In this header, you should import all the public headers of your framework using statements like #import 17 | 18 | 19 | -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SCNText2D-macOSTestApp 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import Cocoa 9 | 10 | @NSApplicationMain 11 | class AppDelegate: NSObject, NSApplicationDelegate { 12 | 13 | func applicationDidFinishLaunching(_ aNotification: Notification) { 14 | // Insert code here to initialize your application 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/GameViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GameViewController.swift 3 | // SCNText2D-macOSTestApp 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import SceneKit 9 | import QuartzCore 10 | 11 | import SCNText2D 12 | 13 | class GameViewController: NSViewController { 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | // create a new scene 19 | let scene = SCNScene() 20 | 21 | // create and add a camera to the scene 22 | let cameraNode = SCNNode() 23 | cameraNode.camera = SCNCamera() 24 | scene.rootNode.addChildNode(cameraNode) 25 | 26 | // place the camera 27 | cameraNode.position = SCNVector3(x: 0, y: 0, z: 15) 28 | 29 | // create and add a light to the scene 30 | let lightNode = SCNNode() 31 | lightNode.light = SCNLight() 32 | lightNode.light!.type = .omni 33 | lightNode.position = SCNVector3(x: 0, y: 10, z: 10) 34 | scene.rootNode.addChildNode(lightNode) 35 | 36 | // create and add an ambient light to the scene 37 | let ambientLightNode = SCNNode() 38 | ambientLightNode.light = SCNLight() 39 | ambientLightNode.light!.type = .ambient 40 | ambientLightNode.light!.color = NSColor.darkGray 41 | scene.rootNode.addChildNode(ambientLightNode) 42 | 43 | // retrieve the SCNView 44 | let scnView = self.view as! SCNView 45 | 46 | // set the scene to the view 47 | scnView.scene = scene 48 | 49 | // allows the user to manipulate the camera 50 | scnView.allowsCameraControl = true 51 | 52 | // show statistics such as fps and timing information 53 | scnView.showsStatistics = true 54 | 55 | // configure the view 56 | scnView.backgroundColor = NSColor.black 57 | 58 | let text = 59 | """ 60 | It is a period of civil war. 61 | Rebel spaceships, striking 62 | from a hidden base, have won 63 | their first victory against 64 | the evil Galactic Empire. 65 | 66 | During the battle, Rebel 67 | spies managed to steal secret 68 | plans to the Empire's 69 | ultimate weapon, the DEATH 70 | STAR, an armored space 71 | station with enough power to 72 | destroy an entire planet. 73 | 74 | Pursued by the Empire's 75 | sinister agents, Princess 76 | Leia races home aboard her 77 | starship, custodian of the 78 | stolen plans that can save 79 | her people and restore 80 | freedom to the galaxy..... 81 | """ 82 | 83 | let fontConfig = SCNText2D.SDFParams( 84 | smoothing: 0.1, 85 | fontWidth: 0.9, 86 | outlineWidth: 0.5, 87 | shadowWidth: 0.5, 88 | shadowOffset: float2(0.0, 0.0), 89 | fontColor: float4(0.0, 0.0, 0.0, 1.0), 90 | outlineColor: float4(1.0, 1.0, 0.0, 1.0), 91 | shadowColor: float4(0.0, 0.0, 0.0, 0.0) 92 | ) 93 | 94 | SCNText2D.load(font: "OpenSans-Regular", bundle: Bundle.main, fontConfig: fontConfig) 95 | 96 | let textGeometry = SCNText2D.create(from: text, 97 | withFontNamed: "OpenSans-Regular", 98 | alignment: .centered) 99 | 100 | let node = SCNNode() 101 | node.eulerAngles.x += -35.0 * (180.0 / .pi) 102 | 103 | let textNode = SCNNode() 104 | textNode.geometry = textGeometry 105 | 106 | let moveAction = SCNAction.move(by: SCNVector3(x:0, y: 200.0, z: 0.0), duration: 240.0) 107 | textNode.runAction(moveAction) 108 | 109 | node.addChildNode(textNode) 110 | 111 | scene.rootNode.addChildNode(node) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 0.1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSMainStoryboardFile 26 | Main 27 | NSPrincipalClass 28 | NSApplication 29 | 30 | 31 | -------------------------------------------------------------------------------- /SCNText2D-macOSTestApp/SCNText2D_macOSTestApp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SCNText2D-macOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 0.1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SCNText2D-macOSTests/SCNText2D_macOSTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNText2D_macOSTests.swift 3 | // SCNText2D-macOSTests 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import XCTest 9 | @testable import SCNText2D 10 | 11 | class SCNText2D_macOSTests: XCTestCase { 12 | 13 | override func setUp() { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | SCNText2D.load(font: "OpenSans-Regular", bundle: Bundle(for: SCNText2D_macOSTests.self)) 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | let geometry = SCNText2D.create(from: "test test test", withFontNamed: "OpenSans-Regular") 26 | 27 | XCTAssert(geometry.elementCount == 1) 28 | } 29 | 30 | func testPerformanceLoadFont() { 31 | self.measure { 32 | SCNText2D.load(font: "OpenSans-Regular", bundle: Bundle(for: SCNText2D_macOSTests.self)) 33 | } 34 | } 35 | 36 | func testPerformanceCreateGeometry() { 37 | 38 | let text = 39 | """ 40 | It is a period of civil war. 41 | Rebel spaceships, striking 42 | from a hidden base, have won 43 | their first victory against 44 | the evil Galactic Empire. 45 | 46 | During the battle, Rebel 47 | spies managed to steal secret 48 | plans to the Empire's 49 | ultimate weapon, the DEATH 50 | STAR, an armored space 51 | station with enough power to 52 | destroy an entire planet. 53 | 54 | Pursued by the Empire's 55 | sinister agents, Princess 56 | Leia races home aboard her 57 | starship, custodian of the 58 | stolen plans that can save 59 | her people and restore 60 | freedom to the galaxy..... 61 | """ 62 | 63 | self.measure { 64 | let _ = SCNText2D.create(from: text, withFontNamed: "OpenSans-Regular") 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcbaselines/4BF7E9AA220FDAF8002E8328.xcbaseline/2102A3E8-DB19-4C1B-A499-83BAC82A6AA8.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | SCNText2D_macOSTests 8 | 9 | testPerformanceCreateGeometry() 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 0.671 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | testPerformanceExample() 20 | 21 | com.apple.XCTPerformanceMetric_WallClockTime 22 | 23 | baselineAverage 24 | 0.0484 25 | baselineIntegrationDisplayName 26 | Local Baseline 27 | 28 | 29 | testPerformanceLoadFont() 30 | 31 | com.apple.XCTPerformanceMetric_WallClockTime 32 | 33 | baselineAverage 34 | 0.066044 35 | baselineIntegrationDisplayName 36 | Local Baseline 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcbaselines/4BF7E9AA220FDAF8002E8328.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | 2102A3E8-DB19-4C1B-A499-83BAC82A6AA8 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 400 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i7 17 | cpuSpeedInMHz 18 | 2600 19 | logicalCPUCoresPerPackage 20 | 12 21 | modelCode 22 | MacBookPro15,1 23 | physicalCPUCoresPerPackage 24 | 6 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcschemes/SCNText2D-Shaders-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcschemes/SCNText2D-Shaders-macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcschemes/SCNText2D-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /SCNText2D.xcodeproj/xcshareddata/xcschemes/SCNText2D-macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Shared/AtlasData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AtlasData.swift 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 15/05/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | class AtlasMetaData: Codable { 11 | 12 | let width: Float 13 | let height: Float 14 | let image: String 15 | } 16 | 17 | class AtlasData: Codable { 18 | 19 | let meta: AtlasMetaData 20 | let frames: Dictionary> 21 | } 22 | -------------------------------------------------------------------------------- /Shared/Font/crocodile_feet.json: -------------------------------------------------------------------------------- 1 | {"ascender":0.865385,"bitmap_height":1024,"bitmap_width":1024,"descender":-0.237179,"glyph_data":{" ":{"advance_x":0.220002,"bbox_height":0.153846,"bbox_width":0.153846,"bearing_x":-0.076923,"bearing_y":0.076923,"charcode":" ","kernings":{},"s0":0,"s1":0.023438,"t0":0.023438,"t1":0},"!":{"advance_x":0.170999,"bbox_height":0.827843,"bbox_width":0.307843,"bearing_x":-0.060096,"bearing_y":0.751202,"charcode":"!","kernings":{},"s0":0.023438,"s1":0.070312,"t0":0.125977,"t1":0},"\"":{"advance_x":0.353998,"bbox_height":0.378850,"bbox_width":0.491843,"bearing_x":-0.080128,"bearing_y":0.782051,"charcode":"\"","kernings":{"A":-0.057692,"B":-0.032051,"C":-0.038462,"D":-0.044872,"E":-0.032051,"G":-0.038462,"L":-0.076923,"O":-0.064103,"Q":-0.057692,"S":-0.044872,"a":-0.076923,"b":-0.096154,"c":-0.032051,"e":-0.051282,"o":-0.044872,"p":-0.025641,"s":-0.006410},"s0":0.070312,"s1":0.144531,"t0":0.057617,"t1":0},"#":{"advance_x":0.510999,"bbox_height":0.649846,"bbox_width":0.624843,"bearing_x":-0.057292,"bearing_y":0.651042,"charcode":"#","kernings":{},"s0":0.144531,"s1":0.239258,"t0":0.098633,"t1":0},"$":{"advance_x":0.384997,"bbox_height":0.979849,"bbox_width":0.498848,"bearing_x":-0.057292,"bearing_y":0.813301,"charcode":"$","kernings":{},"s0":0.239258,"s1":0.314453,"t0":0.148438,"t1":0},"%":{"advance_x":0.492000,"bbox_height":0.823843,"bbox_width":0.605844,"bearing_x":-0.057292,"bearing_y":0.747196,"charcode":"%","kernings":{},"s0":0.314453,"s1":0.406250,"t0":0.125000,"t1":0},"&":{"advance_x":0.541003,"bbox_height":0.906845,"bbox_width":0.784850,"bearing_x":-0.187099,"bearing_y":0.717147,"charcode":"&","kernings":{"C":-0.012821,"E":-0.032051,"F":-0.032051,"K":-0.057692,"L":-0.012821,"R":-0.038462,"T":-0.025641,"V":-0.057692,"W":-0.038462,"X":-0.051282,"Y":-0.076923,"f":-0.012821,"h":-0.006410,"k":-0.032051,"n":-0.006410,"r":-0.032051,"t":-0.032051,"v":-0.044872,"x":-0.025641},"s0":0.406250,"s1":0.525391,"t0":0.137695,"t1":0},"'":{"advance_x":0.176000,"bbox_height":0.378850,"bbox_width":0.313846,"bearing_x":-0.080128,"bearing_y":0.782051,"charcode":"'","kernings":{},"s0":0.525391,"s1":0.573242,"t0":0.057617,"t1":0},"(":{"advance_x":0.231001,"bbox_height":0.823843,"bbox_width":0.418845,"bearing_x":-0.131010,"bearing_y":0.747196,"charcode":"(","kernings":{},"s0":0.573242,"s1":0.636719,"t0":0.125000,"t1":0},")":{"advance_x":0.231001,"bbox_height":0.823843,"bbox_width":0.418845,"bearing_x":-0.057292,"bearing_y":0.747196,"charcode":")","kernings":{"0":-0.044872,"2":-0.012821,"3":-0.032051,"5":-0.038462,"6":-0.038462,"7":-0.038462,"8":-0.038462,"9":-0.038462,"B":-0.032051,"C":-0.044872,"F":-0.032051,"G":-0.032051,"O":-0.044872,"P":-0.038462,"Q":-0.012821,"S":-0.038462,"U":-0.012821,"V":-0.038462,"W":-0.032051,"X":-0.012821,"Y":-0.038462,"b":-0.025641,"e":-0.038462,"o":-0.038462,"p":-0.064103,"r":-0.064103,"s":-0.006410,"v":-0.076923,"w":-0.032051,"x":-0.012821},"s0":0.636719,"s1":0.700195,"t0":0.125000,"t1":0},"*":{"advance_x":0.275998,"bbox_height":0.400848,"bbox_width":0.389843,"bearing_x":-0.057292,"bearing_y":0.769231,"charcode":"*","kernings":{},"s0":0.700195,"s1":0.758789,"t0":0.060547,"t1":0},"+":{"advance_x":0.404003,"bbox_height":0.515850,"bbox_width":0.517847,"bearing_x":-0.057292,"bearing_y":0.504006,"charcode":"+","kernings":{},"s0":0.758789,"s1":0.836914,"t0":0.078125,"t1":0},",":{"advance_x":0.160000,"bbox_height":0.374844,"bbox_width":0.327843,"bearing_x":-0.057292,"bearing_y":0.182292,"charcode":",","kernings":{},"s0":0.836914,"s1":0.886719,"t0":0.056641,"t1":0},"-":{"advance_x":0.338999,"bbox_height":0.258845,"bbox_width":0.452843,"bearing_x":-0.057292,"bearing_y":0.381010,"charcode":"-","kernings":{"1":-0.038462,"2":-0.025641,"7":-0.083333,"C":-0.032051,"E":-0.064103,"F":-0.083333,"K":-0.102564,"L":-0.038462,"R":-0.044872,"T":-0.070513,"V":-0.044872,"W":-0.051282,"X":-0.076923,"Y":-0.121795,"f":-0.057692,"k":-0.057692,"r":-0.070513,"t":-0.038462,"v":-0.051282,"x":-0.064103},"s0":0.886719,"s1":0.955078,"t0":0.039062,"t1":0},".":{"advance_x":0.147999,"bbox_height":0.258845,"bbox_width":0.261844,"bearing_x":-0.057292,"bearing_y":0.181090,"charcode":".","kernings":{"3":-0.064103,"5":-0.057692,"6":-0.032051,"7":-0.121795,"8":-0.038462,"9":-0.083333,"B":-0.064103,"C":-0.044872,"D":-0.064103,"F":-0.108974,"O":-0.064103,"P":-0.141026,"T":-0.083333,"V":-0.102564,"W":-0.108974,"Y":-0.134615,"b":-0.044872,"e":-0.032051,"f":-0.070513,"o":-0.032051,"p":-0.044872,"r":-0.108974,"v":-0.102564,"w":-0.025641},"s0":0.955078,"s1":0.994141,"t0":0.039062,"t1":0},"\/":{"advance_x":0.276999,"bbox_height":0.836845,"bbox_width":0.390844,"bearing_x":-0.057292,"bearing_y":0.761218,"charcode":"\/","kernings":{"B":-0.044872,"C":-0.019231,"D":-0.032051,"F":-0.070513,"O":-0.044872,"P":-0.070513,"Q":-0.012821,"S":-0.019231,"T":-0.070513,"U":-0.019231,"V":-0.070513,"W":-0.064103,"Y":-0.102564,"b":-0.025641,"e":-0.012821,"f":-0.038462,"p":-0.032051,"r":-0.076923,"v":-0.070513,"w":-0.025641},"s0":0.886719,"s1":0.946289,"t0":0.166016,"t1":0.039062},"0":{"advance_x":0.447998,"bbox_height":0.735846,"bbox_width":0.561843,"bearing_x":-0.057292,"bearing_y":0.677083,"charcode":"0","kernings":{"(":-0.064103,"1":-0.038462,"2":-0.032051,"7":-0.064103,"[":-0.064103},"s0":0.700195,"s1":0.785156,"t0":0.189453,"t1":0.078125},"1":{"advance_x":0.350999,"bbox_height":0.744848,"bbox_width":0.464844,"bearing_x":-0.057292,"bearing_y":0.678285,"charcode":"1","kernings":{"(":-0.032051,"-":-0.038462,"0":-0.012821,"3":-0.038462,"5":-0.057692,"6":-0.044872,"7":-0.057692,"8":-0.044872,"9":-0.012821,"[":-0.025641},"s0":0.070312,"s1":0.140625,"t0":0.170898,"t1":0.057617},"2":{"advance_x":0.397999,"bbox_height":0.765844,"bbox_width":0.511844,"bearing_x":-0.057292,"bearing_y":0.717147,"charcode":"2","kernings":{"(":-0.006410,"-":-0.038462,"0":-0.038462,"1":-0.006410,"3":-0.044872,"5":-0.044872,"6":-0.044872,"7":-0.038462,"8":-0.038462,"9":-0.032051},"s0":0.785156,"s1":0.862305,"t0":0.194336,"t1":0.078125},"3":{"advance_x":0.404998,"bbox_height":0.738845,"bbox_width":0.518843,"bearing_x":-0.057292,"bearing_y":0.691106,"charcode":"3","kernings":{"(":-0.025641,"-":-0.070513,"0":-0.064103,"1":-0.032051,"2":-0.032051,"5":-0.044872,"6":-0.064103,"7":-0.025641,"8":-0.051282,"9":-0.038462,"[":-0.006410},"s0":0.140625,"s1":0.219727,"t0":0.210938,"t1":0.098633},"4":{"advance_x":0.396998,"bbox_height":0.737843,"bbox_width":0.510842,"bearing_x":-0.057292,"bearing_y":0.669071,"charcode":"4","kernings":{"(":-0.070513,"1":-0.038462,"2":-0.057692,"3":-0.025641,"7":-0.096154,"[":-0.051282,"_":-0.173077},"s0":0.525391,"s1":0.602539,"t0":0.237305,"t1":0.125000},"5":{"advance_x":0.397999,"bbox_height":0.741843,"bbox_width":0.511844,"bearing_x":-0.057292,"bearing_y":0.681090,"charcode":"5","kernings":{"(":-0.025641,"1":-0.025641,"2":-0.012821,"3":-0.032051,"5":-0.032051,"6":-0.012821,"7":-0.032051,"8":-0.032051,"[":-0.044872},"s0":0.314453,"s1":0.391602,"t0":0.237305,"t1":0.125000},"6":{"advance_x":0.445000,"bbox_height":0.773844,"bbox_width":0.558844,"bearing_x":-0.057292,"bearing_y":0.705930,"charcode":"6","kernings":{"(":-0.057692,"1":-0.038462,"2":-0.025641,"5":-0.012821,"7":-0.064103,"[":-0.038462,"_":-0.057692},"s0":0.602539,"s1":0.687500,"t0":0.242188,"t1":0.125000},"7":{"advance_x":0.422000,"bbox_height":0.747847,"bbox_width":0.535845,"bearing_x":-0.057292,"bearing_y":0.689103,"charcode":"7","kernings":{"-":-0.070513,"0":-0.064103,"3":-0.038462,"5":-0.057692,"6":-0.070513,"7":-0.012821,"8":-0.083333,"9":-0.057692,"_":-0.064103},"s0":0.391602,"s1":0.472656,"t0":0.250977,"t1":0.137695},"8":{"advance_x":0.470002,"bbox_height":0.793845,"bbox_width":0.588848,"bearing_x":-0.062099,"bearing_y":0.717949,"charcode":"8","kernings":{"(":-0.025641,"1":-0.025641,"7":-0.064103,"[":-0.025641,"_":-0.025641},"s0":0.219727,"s1":0.308594,"t0":0.268555,"t1":0.148438},"9":{"advance_x":0.440999,"bbox_height":0.767847,"bbox_width":0.554844,"bearing_x":-0.057292,"bearing_y":0.707131,"charcode":"9","kernings":{"(":-0.038462,"-":-0.044872,"0":-0.025641,"1":-0.044872,"3":-0.038462,"5":-0.057692,"6":-0.064103,"7":-0.038462,"8":-0.064103,"[":-0.064103,"_":-0.064103},"s0":0.862305,"s1":0.946289,"t0":0.282227,"t1":0.166016},":":{"advance_x":0.147999,"bbox_height":0.507850,"bbox_width":0.261844,"bearing_x":-0.057292,"bearing_y":0.430288,"charcode":":","kernings":{},"s0":0.946289,"s1":0.985352,"t0":0.116211,"t1":0.039062},";":{"advance_x":0.160000,"bbox_height":0.622847,"bbox_width":0.327843,"bearing_x":-0.057292,"bearing_y":0.430288,"charcode":";","kernings":{},"s0":0.946289,"s1":0.996094,"t0":0.210938,"t1":0.116211},"<":{"advance_x":0.369998,"bbox_height":0.482841,"bbox_width":0.483843,"bearing_x":-0.057292,"bearing_y":0.461939,"charcode":"<","kernings":{},"s0":0,"s1":0.073242,"t0":0.244141,"t1":0.170898},"=":{"advance_x":0.435998,"bbox_height":0.424849,"bbox_width":0.549848,"bearing_x":-0.057292,"bearing_y":0.448317,"charcode":"=","kernings":{},"s0":0.687500,"s1":0.770508,"t0":0.253906,"t1":0.189453},">":{"advance_x":0.369998,"bbox_height":0.482841,"bbox_width":0.483843,"bearing_x":-0.057292,"bearing_y":0.461939,"charcode":">","kernings":{},"s0":0.770508,"s1":0.843750,"t0":0.267578,"t1":0.194336},"?":{"advance_x":0.397999,"bbox_height":0.843844,"bbox_width":0.511844,"bearing_x":-0.057292,"bearing_y":0.749199,"charcode":"?","kernings":{"A":-0.051282,"C":-0.032051,"D":-0.051282,"E":-0.038462,"F":-0.012821,"G":-0.019231,"K":-0.051282,"L":-0.102564,"O":-0.044872,"P":-0.019231,"Q":-0.038462,"R":-0.032051,"S":-0.012821,"V":-0.019231,"W":-0.019231,"X":-0.051282,"Y":-0.051282,"a":-0.070513,"b":-0.096154,"c":-0.070513,"d":-0.038462,"e":-0.070513,"g":-0.070513,"h":-0.070513,"j":-0.019231,"k":-0.032051,"m":-0.096154,"n":-0.102564,"o":-0.096154,"p":-0.083333,"q":-0.064103,"r":-0.070513,"s":-0.083333,"t":-0.051282,"u":-0.070513,"v":-0.064103,"w":-0.070513,"x":-0.083333,"y":-0.051282,"z":-0.038462},"s0":0.073242,"s1":0.150391,"t0":0.338867,"t1":0.210938},"@":{"advance_x":0.598001,"bbox_height":0.909843,"bbox_width":0.749844,"bearing_x":-0.088942,"bearing_y":0.709135,"charcode":"@","kernings":{"C":-0.032051,"F":-0.064103,"K":-0.076923,"L":-0.057692,"R":-0.025641,"S":-0.012821,"T":-0.070513,"V":-0.070513,"W":-0.057692,"X":-0.064103,"Y":-0.083333,"f":-0.032051,"k":-0.038462,"r":-0.012821,"t":-0.044872,"v":-0.012821,"x":-0.032051},"s0":0.472656,"s1":0.586914,"t0":0.375977,"t1":0.237305},"A":{"advance_x":0.427997,"bbox_height":0.791848,"bbox_width":0.645846,"bearing_x":-0.139022,"bearing_y":0.729968,"charcode":"A","kernings":{"\"":-0.032051,"&":-0.032051,"\/":-0.051282,"F":-0.032051,"K":-0.044872,"S":-0.025641,"T":-0.044872,"V":-0.038462,"W":-0.057692,"X":-0.025641,"Y":-0.070513},"s0":0.586914,"s1":0.684570,"t0":0.362305,"t1":0.242188},"B":{"advance_x":0.392998,"bbox_height":0.866849,"bbox_width":0.577843,"bearing_x":-0.057292,"bearing_y":0.813301,"charcode":"B","kernings":{"&":-0.025641,"Y":-0.012821},"s0":0.308594,"s1":0.396484,"t0":0.382812,"t1":0.250977},"C":{"advance_x":0.462002,"bbox_height":0.915847,"bbox_width":0.583847,"bearing_x":-0.065304,"bearing_y":0.713141,"charcode":"C","kernings":{"\"":-0.076923,"&":-0.032051,"(":-0.057692,"\/":-0.064103,"A":-0.025641,"C":-0.038462,"E":-0.051282,"F":-0.032051,"K":-0.083333,"L":-0.044872,"P":-0.025641,"R":-0.012821,"S":-0.025641,"T":-0.032051,"V":-0.051282,"W":-0.038462,"X":-0.064103,"Y":-0.083333,"Z":-0.025641,"\\":-0.038462,"_":-0.064103},"s0":0.684570,"s1":0.773438,"t0":0.406250,"t1":0.267578},"D":{"advance_x":0.419002,"bbox_height":0.803849,"bbox_width":0.534843,"bearing_x":-0.057292,"bearing_y":0.707131,"charcode":"D","kernings":{"&":-0.025641,"C":-0.006410,"K":-0.032051,"V":-0.025641,"W":-0.032051,"Y":-0.025641},"s0":0.773438,"s1":0.854492,"t0":0.389648,"t1":0.267578},"E":{"advance_x":0.358999,"bbox_height":0.748848,"bbox_width":0.472844,"bearing_x":-0.057292,"bearing_y":0.692308,"charcode":"E","kernings":{"(":-0.012821,"C":-0.032051,"K":-0.012821,"P":-0.006410,"W":-0.025641,"Y":-0.025641},"s0":0,"s1":0.071289,"t0":0.357422,"t1":0.244141},"F":{"advance_x":0.317001,"bbox_height":0.763847,"bbox_width":0.430846,"bearing_x":-0.057292,"bearing_y":0.705128,"charcode":"F","kernings":{"&":-0.032051},"s0":0.150391,"s1":0.215820,"t0":0.327148,"t1":0.210938},"G":{"advance_x":0.447998,"bbox_height":0.805846,"bbox_width":0.566844,"bearing_x":-0.062099,"bearing_y":0.705930,"charcode":"G","kernings":{"\"":-0.064103,"&":-0.032051,"(":-0.064103,"\/":-0.044872,"A":-0.025641,"B":-0.012821,"C":-0.038462,"E":-0.057692,"F":-0.064103,"K":-0.096154,"L":-0.064103,"P":-0.012821,"Q":-0.012821,"R":-0.012821,"S":-0.025641,"T":-0.044872,"V":-0.064103,"W":-0.044872,"X":-0.083333,"Y":-0.096154,"Z":-0.025641,"\\":-0.032051,"_":-0.083333},"s0":0.215820,"s1":0.301758,"t0":0.390625,"t1":0.268555},"H":{"advance_x":0.420999,"bbox_height":0.773844,"bbox_width":0.534843,"bearing_x":-0.057292,"bearing_y":0.713141,"charcode":"H","kernings":{"&":-0.032051,"B":-0.025641,"C":-0.038462,"D":-0.032051,"E":-0.032051,"K":-0.032051,"L":-0.025641,"O":-0.012821,"R":-0.025641,"S":-0.012821,"X":-0.006410,"Y":-0.006410},"s0":0.854492,"s1":0.935547,"t0":0.399414,"t1":0.282227},"I":{"advance_x":0.184001,"bbox_height":0.755847,"bbox_width":0.297845,"bearing_x":-0.057292,"bearing_y":0.692308,"charcode":"I","kernings":{"K":-0.025641,"W":-0.032051,"X":-0.032051,"Y":-0.032051},"s0":0.946289,"s1":0.991211,"t0":0.326172,"t1":0.210938},"J":{"advance_x":0.357002,"bbox_height":0.792850,"bbox_width":0.479843,"bearing_x":-0.057292,"bearing_y":0.711138,"charcode":"J","kernings":{"\"":-0.153846,"&":-0.051282,"-":-0.076923,"\/":-0.102564,"@":-0.057692,"A":-0.012821,"B":-0.064103,"C":-0.044872,"D":-0.064103,"E":-0.012821,"F":-0.153846,"G":-0.025641,"J":-0.051282,"K":-0.064103,"L":-0.025641,"M":-0.025641,"N":-0.025641,"O":-0.064103,"P":-0.166667,"Q":-0.076923,"R":-0.044872,"S":-0.038462,"T":-0.102564,"U":-0.044872,"V":-0.134615,"W":-0.121795,"X":-0.051282,"Y":-0.153846,"Z":-0.025641},"s0":0.396484,"s1":0.468750,"t0":0.371094,"t1":0.250977},"K":{"advance_x":0.420999,"bbox_height":0.781851,"bbox_width":0.534843,"bearing_x":-0.057292,"bearing_y":0.723157,"charcode":"K","kernings":{"K":-0.012821},"s0":0.071289,"s1":0.152344,"t0":0.458008,"t1":0.338867},"L":{"advance_x":0.310998,"bbox_height":0.794847,"bbox_width":0.424849,"bearing_x":-0.057292,"bearing_y":0.723157,"charcode":"L","kernings":{},"s0":0.935547,"s1":1,"t0":0.447266,"t1":0.326172},"M":{"advance_x":0.556002,"bbox_height":0.780849,"bbox_width":0.669847,"bearing_x":-0.057292,"bearing_y":0.713942,"charcode":"M","kernings":{"B":-0.012821,"C":-0.012821,"K":-0.032051,"Q":-0.012821,"V":-0.032051,"W":-0.012821,"X":-0.012821},"s0":0.468750,"s1":0.570312,"t0":0.494141,"t1":0.375977},"N":{"advance_x":0.471999,"bbox_height":0.759847,"bbox_width":0.585844,"bearing_x":-0.057292,"bearing_y":0.709135,"charcode":"N","kernings":{"Y":-0.032051},"s0":0.586914,"s1":0.675781,"t0":0.477539,"t1":0.362305},"O":{"advance_x":0.548997,"bbox_height":0.806847,"bbox_width":0.751847,"bearing_x":-0.057292,"bearing_y":0.733173,"charcode":"O","kernings":{"\"":-0.064103,"&":-0.038462,"(":-0.064103,"\/":-0.038462,"C":-0.044872,"E":-0.032051,"K":-0.096154,"L":-0.064103,"P":-0.006410,"Q":-0.006410,"R":-0.012821,"S":-0.032051,"T":-0.038462,"V":-0.051282,"W":-0.051282,"X":-0.083333,"Y":-0.096154,"Z":-0.044872,"\\":-0.019231,"_":-0.083333},"s0":0.301758,"s1":0.416016,"t0":0.504883,"t1":0.382812},"P":{"advance_x":0.379000,"bbox_height":0.810847,"bbox_width":0.507844,"bearing_x":-0.057292,"bearing_y":0.735176,"charcode":"P","kernings":{"K":-0.025641,"L":-0.012821},"s0":0.773438,"s1":0.850586,"t0":0.512695,"t1":0.389648},"Q":{"advance_x":0.540002,"bbox_height":0.864846,"bbox_width":0.658848,"bearing_x":-0.062099,"bearing_y":0.707933,"charcode":"Q","kernings":{"\"":-0.064103,"&":-0.038462,"(":-0.064103,"\/":-0.038462,"C":-0.051282,"E":-0.044872,"F":-0.044872,"K":-0.083333,"L":-0.070513,"Q":-0.006410,"R":-0.025641,"S":-0.038462,"T":-0.064103,"V":-0.051282,"W":-0.064103,"X":-0.076923,"Y":-0.096154,"Z":-0.032051,"\\":-0.019231,"_":-0.083333},"s0":0.152344,"s1":0.251953,"t0":0.521484,"t1":0.390625},"R":{"advance_x":0.406000,"bbox_height":0.778846,"bbox_width":0.523844,"bearing_x":-0.057292,"bearing_y":0.698317,"charcode":"R","kernings":{"C":-0.006410,"K":-0.025641,"W":-0.032051,"X":-0.032051,"Y":-0.032051},"s0":0.850586,"s1":0.929688,"t0":0.517578,"t1":0.399414},"S":{"advance_x":0.384997,"bbox_height":0.779848,"bbox_width":0.498848,"bearing_x":-0.057292,"bearing_y":0.703125,"charcode":"S","kernings":{"\"":-0.057692,"&":-0.044872,"(":-0.038462,"-":-0.032051,"\/":-0.019231,"@":-0.025641,"C":-0.012821,"D":-0.032051,"F":-0.032051,"G":-0.012821,"K":-0.070513,"L":-0.025641,"O":-0.012821,"P":-0.032051,"Q":-0.025641,"R":-0.012821,"S":-0.032051,"T":-0.032051,"V":-0.044872,"W":-0.044872,"X":-0.064103,"Y":-0.076923,"Z":-0.006410,"\\":-0.019231,"_":-0.038462},"s0":0.675781,"s1":0.750977,"t0":0.524414,"t1":0.406250},"T":{"advance_x":0.357998,"bbox_height":0.784850,"bbox_width":0.471842,"bearing_x":-0.057292,"bearing_y":0.725962,"charcode":"T","kernings":{"&":-0.102564,"-":-0.070513,"@":-0.044872,"A":-0.070513,"B":-0.025641,"C":-0.057692,"D":-0.070513,"E":-0.032051,"G":-0.032051,"K":-0.006410,"L":-0.108974,"O":-0.070513,"P":-0.057692,"Q":-0.070513,"R":-0.032051,"S":-0.032051,"X":-0.012821,"Y":-0.025641,"\\":-0.051282,"_":-0.083333},"s0":0,"s1":0.071289,"t0":0.476562,"t1":0.357422},"U":{"advance_x":0.449000,"bbox_height":0.790847,"bbox_width":0.687844,"bearing_x":-0.108173,"bearing_y":0.717147,"charcode":"U","kernings":{"&":-0.032051,"(":-0.025641,"C":-0.032051,"E":-0.032051,"K":-0.032051,"L":-0.064103,"S":-0.025641,"W":-0.038462,"X":-0.038462,"Y":-0.038462,"\\":-0.019231,"_":-0.083333},"s0":0,"s1":0.104492,"t0":0.596680,"t1":0.476562},"V":{"advance_x":0.521998,"bbox_height":0.762846,"bbox_width":0.635842,"bearing_x":-0.057292,"bearing_y":0.703125,"charcode":"V","kernings":{"&":-0.108974,"(":-0.038462,"-":-0.102564,"@":-0.064103,"A":-0.076923,"B":-0.038462,"C":-0.064103,"D":-0.076923,"E":-0.057692,"G":-0.044872,"K":-0.032051,"L":-0.121795,"O":-0.057692,"P":-0.057692,"Q":-0.076923,"R":-0.044872,"S":-0.038462,"U":-0.032051,"X":-0.032051,"Y":-0.025641,"Z":-0.025641,"\\":-0.083333,"_":-0.141026},"s0":0.570312,"s1":0.666992,"t0":0.593750,"t1":0.477539},"W":{"advance_x":0.720002,"bbox_height":0.783848,"bbox_width":0.833847,"bearing_x":-0.057292,"bearing_y":0.717147,"charcode":"W","kernings":{"&":-0.076923,"-":-0.083333,"@":-0.038462,"A":-0.057692,"B":-0.025641,"C":-0.051282,"D":-0.044872,"E":-0.038462,"G":-0.032051,"K":-0.044872,"L":-0.102564,"M":-0.025641,"N":-0.012821,"O":-0.051282,"P":-0.044872,"Q":-0.057692,"R":-0.038462,"S":-0.032051,"X":-0.012821,"Y":-0.006410,"\\":-0.064103,"_":-0.115385},"s0":0.416016,"s1":0.542969,"t0":0.613281,"t1":0.494141},"X":{"advance_x":0.496000,"bbox_height":0.773844,"bbox_width":0.609845,"bearing_x":-0.057292,"bearing_y":0.713141,"charcode":"X","kernings":{"&":-0.025641,"(":-0.025641,"-":-0.096154,"@":-0.064103,"A":-0.032051,"B":-0.057692,"C":-0.064103,"D":-0.096154,"F":-0.032051,"J":-0.025641,"K":-0.012821,"L":-0.032051,"M":-0.032051,"O":-0.076923,"P":-0.083333,"Q":-0.038462,"R":-0.025641,"S":-0.064103,"T":-0.025641,"U":-0.038462,"V":-0.032051,"W":-0.044872,"X":-0.032051,"Y":-0.038462,"Z":-0.025641,"\\":-0.019231},"s0":0.251953,"s1":0.344727,"t0":0.622070,"t1":0.504883},"Y":{"advance_x":0.492000,"bbox_height":0.769844,"bbox_width":0.605844,"bearing_x":-0.057292,"bearing_y":0.709135,"charcode":"Y","kernings":{"&":-0.153846,"(":-0.025641,"-":-0.134615,"@":-0.076923,"A":-0.083333,"B":-0.051282,"C":-0.070513,"D":-0.096154,"E":-0.044872,"F":-0.032051,"G":-0.051282,"I":-0.051282,"K":-0.025641,"L":-0.141026,"M":-0.032051,"N":-0.006410,"O":-0.102564,"P":-0.076923,"Q":-0.108974,"R":-0.064103,"S":-0.070513,"U":-0.032051,"V":-0.025641,"X":-0.044872,"Y":-0.032051,"Z":-0.006410,"\\":-0.096154,"_":-0.166667},"s0":0.750977,"s1":0.842773,"t0":0.629883,"t1":0.512695},"Z":{"advance_x":0.420999,"bbox_height":0.753844,"bbox_width":0.534843,"bearing_x":-0.057292,"bearing_y":0.709135,"charcode":"Z","kernings":{"&":-0.038462,"-":-0.025641,"@":-0.025641,"A":-0.012821,"B":-0.025641,"C":-0.038462,"D":-0.038462,"E":-0.025641,"G":0.006410,"K":-0.012821,"L":-0.025641,"O":-0.038462,"P":-0.044872,"Q":-0.044872,"S":-0.012821,"W":-0.025641,"Y":-0.032051,"\\":-0.012821},"s0":0.842773,"s1":0.923828,"t0":0.631836,"t1":0.517578},"[":{"advance_x":0.193998,"bbox_height":0.796850,"bbox_width":0.310841,"bearing_x":-0.060096,"bearing_y":0.721955,"charcode":"[","kernings":{},"s0":0.929688,"s1":0.976562,"t0":0.568359,"t1":0.447266},"\\":{"advance_x":0.276999,"bbox_height":0.836845,"bbox_width":0.390844,"bearing_x":-0.057292,"bearing_y":0.761218,"charcode":"\\","kernings":{"A":-0.064103,"B":-0.032051,"C":-0.044872,"D":-0.038462,"E":-0.038462,"G":-0.032051,"O":-0.051282,"P":-0.032051,"Q":-0.044872,"R":-0.038462,"S":-0.019231,"a":-0.070513,"b":-0.108974,"c":-0.064103,"d":-0.032051,"e":-0.064103,"g":-0.070513,"h":-0.083333,"i":-0.025641,"j":-0.064103,"k":-0.051282,"m":-0.076923,"n":-0.076923,"o":-0.076923,"p":-0.076923,"q":-0.038462,"r":-0.064103,"s":-0.076923,"t":-0.076923,"u":-0.070513,"v":-0.064103,"w":-0.044872,"x":-0.076923,"y":-0.057692,"z":-0.057692},"s0":0.344727,"s1":0.404297,"t0":0.631836,"t1":0.504883},"]":{"advance_x":0.193998,"bbox_height":0.796850,"bbox_width":0.310847,"bearing_x":-0.057292,"bearing_y":0.721955,"charcode":"]","kernings":{"0":-0.044872,"1":-0.025641,"2":-0.012821,"3":-0.044872,"5":-0.044872,"6":-0.064103,"7":-0.012821,"8":-0.057692,"9":-0.044872},"s0":0.104492,"s1":0.151367,"t0":0.579102,"t1":0.458008},"^":{"advance_x":0.385999,"bbox_height":0.347844,"bbox_width":0.499844,"bearing_x":-0.057292,"bearing_y":0.733173,"charcode":"^","kernings":{},"s0":0.151367,"s1":0.227539,"t0":0.574219,"t1":0.521484},"_":{"advance_x":0.479999,"bbox_height":0.223846,"bbox_width":0.593844,"bearing_x":-0.057292,"bearing_y":0.147035,"charcode":"_","kernings":{"0":-0.064103,"3":-0.064103,"5":-0.044872,"6":-0.044872,"7":-0.153846,"8":-0.038462,"9":-0.102564,"B":-0.070513,"C":-0.044872,"D":-0.096154,"F":-0.141026,"J":-0.064103,"O":-0.070513,"P":-0.179487,"S":-0.057692,"T":-0.096154,"U":-0.064103,"V":-0.141026,"W":-0.121795,"Y":-0.166667,"b":-0.032051,"f":-0.070513,"o":-0.032051,"p":-0.083333,"r":-0.173077,"v":-0.134615,"w":-0.032051},"s0":0.151367,"s1":0.241211,"t0":0.607422,"t1":0.574219},"`":{"advance_x":0.197998,"bbox_height":0.265850,"bbox_width":0.311843,"bearing_x":-0.057292,"bearing_y":0.680288,"charcode":"`","kernings":{},"s0":0.666992,"s1":0.713867,"t0":0.564453,"t1":0.524414},"a":{"advance_x":0.385999,"bbox_height":0.661846,"bbox_width":0.532846,"bearing_x":-0.090144,"bearing_y":0.559295,"charcode":"a","kernings":{"\"":-0.070513,"&":-0.032051,"(":-0.012821,"\/":-0.076923,"B":-0.038462,"C":-0.012821,"E":-0.012821,"F":-0.115385,"K":-0.064103,"P":-0.057692,"Q":-0.032051,"R":-0.044872,"S":-0.032051,"T":-0.083333,"V":-0.076923,"W":-0.083333,"X":-0.038462,"Y":-0.121795,"a":-0.012821,"b":-0.025641,"c":-0.025641,"e":-0.025641,"f":-0.044872,"g":-0.012821,"h":-0.006410,"j":-0.006410,"k":-0.044872,"o":-0.006410,"p":-0.032051,"r":-0.044872,"t":-0.025641,"u":-0.006410,"v":-0.044872,"w":-0.025641,"x":-0.032051,"z":-0.012821},"s0":0.666992,"s1":0.748047,"t0":0.665039,"t1":0.564453},"b":{"advance_x":0.376997,"bbox_height":0.776843,"bbox_width":0.490848,"bearing_x":-0.057292,"bearing_y":0.694311,"charcode":"b","kernings":{"\/":-0.012821,"F":-0.012821,"K":-0.012821,"S":-0.012821,"T":-0.025641,"W":-0.032051,"Y":-0.025641,"r":-0.038462},"s0":0.923828,"s1":0.998047,"t0":0.686523,"t1":0.568359},"c":{"advance_x":0.357998,"bbox_height":0.576848,"bbox_width":0.471842,"bearing_x":-0.057292,"bearing_y":0.477163,"charcode":"c","kernings":{"\"":-0.044872,"&":-0.032051,"(":-0.038462,"\/":-0.076923,"B":-0.032051,"C":-0.032051,"E":-0.032051,"F":-0.083333,"K":-0.076923,"L":-0.025641,"O":-0.006410,"P":-0.064103,"Q":-0.032051,"R":-0.070513,"S":-0.012821,"T":-0.083333,"V":-0.096154,"W":-0.102564,"X":-0.070513,"Y":-0.121795,"\\":-0.025641,"_":-0.044872,"a":-0.012821,"c":-0.032051,"e":-0.012821,"f":-0.044872,"i":-0.006410,"k":-0.064103,"n":-0.012821,"r":-0.083333,"s":-0.006410,"t":-0.032051,"u":-0.012821,"v":-0.070513,"x":-0.070513,"z":-0.012821},"s0":0.542969,"s1":0.614258,"t0":0.681641,"t1":0.593750},"d":{"advance_x":0.385999,"bbox_height":0.878850,"bbox_width":0.513847,"bearing_x":-0.071314,"bearing_y":0.762019,"charcode":"d","kernings":{"\"":-0.102564,"&":-0.032051,"(":-0.025641,"\/":-0.076923,"@":-0.025641,"B":-0.038462,"C":-0.012821,"E":-0.025641,"F":-0.102564,"K":-0.051282,"L":-0.025641,"O":-0.012821,"P":-0.064103,"R":-0.051282,"S":-0.012821,"T":-0.083333,"V":-0.096154,"W":-0.083333,"X":-0.051282,"Y":-0.141026,"Z":-0.012821,"_":-0.025641,"a":-0.006410,"c":-0.012821,"d":-0.006410,"e":-0.012821,"f":-0.064103,"i":-0.012821,"k":-0.057692,"r":-0.076923,"t":-0.032051,"v":-0.070513,"x":-0.070513},"s0":0,"s1":0.078125,"t0":0.730469,"t1":0.596680},"e":{"advance_x":0.406000,"bbox_height":0.593844,"bbox_width":0.530843,"bearing_x":-0.057292,"bearing_y":0.509215,"charcode":"e","kernings":{"\"":-0.102564,"&":-0.025641,"(":-0.038462,"\/":-0.064103,"B":-0.032051,"C":-0.025641,"E":-0.025641,"F":-0.083333,"K":-0.051282,"L":-0.025641,"P":-0.032051,"Q":-0.025641,"R":-0.044872,"S":-0.012821,"T":-0.070513,"V":-0.083333,"W":-0.083333,"X":-0.057692,"Y":-0.134615,"Z":-0.025641,"_":-0.032051,"c":-0.025641,"f":-0.032051,"k":-0.064103,"r":-0.051282,"t":-0.032051,"v":-0.064103,"x":-0.044872},"s0":0.078125,"s1":0.158203,"t0":0.697266,"t1":0.607422},"f":{"advance_x":0.260999,"bbox_height":0.838848,"bbox_width":0.374844,"bearing_x":-0.057292,"bearing_y":0.762019,"charcode":"f","kernings":{"&":-0.025641,"K":-0.032051,"L":-0.012821,"S":-0.006410,"Y":-0.044872,"a":-0.006410,"b":-0.025641,"e":-0.012821,"k":-0.006410,"n":-0.006410,"o":-0.012821,"r":-0.032051,"v":-0.025641,"x":-0.025641},"s0":0.158203,"s1":0.214844,"t0":0.734375,"t1":0.607422},"g":{"advance_x":0.392002,"bbox_height":0.715845,"bbox_width":0.567846,"bearing_x":-0.057292,"bearing_y":0.483974,"charcode":"g","kernings":{"\"":-0.096154,"&":-0.025641,"(":-0.070513,"\/":-0.064103,"B":-0.038462,"C":-0.032051,"E":-0.044872,"F":-0.096154,"G":-0.006410,"K":-0.096154,"L":-0.044872,"N":-0.025641,"P":-0.044872,"Q":-0.025641,"R":-0.064103,"S":-0.032051,"T":-0.083333,"V":-0.102564,"W":-0.076923,"X":-0.083333,"Y":-0.141026,"Z":-0.012821,"_":-0.102564,"a":-0.025641,"b":-0.012821,"c":-0.032051,"e":-0.006410,"f":-0.038462,"g":-0.006410,"i":-0.006410,"j":-0.006410,"k":-0.070513,"n":-0.012821,"r":-0.064103,"s":-0.025641,"t":-0.070513,"u":-0.012821,"v":-0.070513,"x":-0.051282,"z":-0.006410},"s0":0.404297,"s1":0.490234,"t0":0.721680,"t1":0.613281},"h":{"advance_x":0.406000,"bbox_height":0.786846,"bbox_width":0.528846,"bearing_x":-0.057292,"bearing_y":0.709936,"charcode":"h","kernings":{"\/":-0.012821,"B":-0.025641,"P":-0.032051,"W":-0.051282,"Y":-0.044872,"b":-0.006410,"c":-0.012821,"k":-0.006410,"p":-0.012821,"r":-0.038462,"s":-0.006410,"v":-0.032051},"s0":0.241211,"s1":0.321289,"t0":0.741211,"t1":0.622070},"i":{"advance_x":0.177997,"bbox_height":0.754845,"bbox_width":0.292844,"bearing_x":-0.057292,"bearing_y":0.693109,"charcode":"i","kernings":{"\"":-0.025641,"\/":-0.032051,"F":-0.032051,"K":-0.012821,"S":-0.025641,"T":-0.032051,"V":-0.038462,"W":-0.038462,"f":-0.032051,"o":-0.012821,"r":-0.025641,"t":-0.012821},"s0":0.614258,"s1":0.658203,"t0":0.708008,"t1":0.593750},"j":{"advance_x":0.189002,"bbox_height":1.009847,"bbox_width":0.457851,"bearing_x":-0.149038,"bearing_y":0.701923,"charcode":"j","kernings":{"\"":-0.032051,"B":-0.006410,"C":-0.012821,"F":-0.012821,"K":-0.032051,"Q":-0.032051,"W":-0.012821,"Y":-0.044872,"b":-0.006410,"e":-0.012821,"f":-0.025641,"g":0.025641,"j":0.032051,"k":-0.012821,"o":-0.012821,"p":-0.012821,"q":0.032051,"r":-0.006410,"s":-0.025641,"t":-0.025641,"v":-0.032051,"x":-0.006410},"s0":0.748047,"s1":0.817383,"t0":0.783203,"t1":0.629883},"k":{"advance_x":0.367000,"bbox_height":0.770846,"bbox_width":0.480844,"bearing_x":-0.057292,"bearing_y":0.697115,"charcode":"k","kernings":{"Y":-0.032051,"b":-0.006410,"k":-0.006410,"r":-0.006410},"s0":0.321289,"s1":0.394531,"t0":0.749023,"t1":0.631836},"l":{"advance_x":0.177002,"bbox_height":0.833847,"bbox_width":0.290847,"bearing_x":-0.057292,"bearing_y":0.762019,"charcode":"l","kernings":{"b":-0.012821,"k":-0.012821},"s0":0.490234,"s1":0.534180,"t0":0.740234,"t1":0.613281},"m":{"advance_x":0.680000,"bbox_height":0.610846,"bbox_width":0.797845,"bearing_x":-0.057292,"bearing_y":0.531250,"charcode":"m","kernings":{"\"":-0.032051,"\/":-0.044872,"C":-0.006410,"F":-0.076923,"K":-0.025641,"L":-0.012821,"S":-0.032051,"T":-0.070513,"V":-0.038462,"W":-0.044872,"Y":-0.108974,"k":-0.012821,"r":-0.006410,"x":-0.006410},"s0":0.817383,"s1":0.938477,"t0":0.779297,"t1":0.686523},"n":{"advance_x":0.445000,"bbox_height":0.609845,"bbox_width":0.558844,"bearing_x":-0.057292,"bearing_y":0.533253,"charcode":"n","kernings":{"\"":-0.032051,"\/":-0.057692,"B":-0.025641,"C":-0.025641,"F":-0.083333,"K":-0.044872,"L":-0.025641,"S":-0.038462,"T":-0.083333,"V":-0.051282,"X":-0.032051,"Y":-0.115385,"k":-0.025641,"r":-0.012821,"v":-0.032051},"s0":0.658203,"s1":0.743164,"t0":0.757812,"t1":0.665039},"o":{"advance_x":0.439998,"bbox_height":0.608843,"bbox_width":0.698843,"bearing_x":-0.130208,"bearing_y":0.517228,"charcode":"o","kernings":{"\"":-0.108974,"&":-0.038462,"(":-0.044872,"\/":-0.083333,"B":-0.032051,"C":-0.025641,"E":-0.025641,"F":-0.076923,"K":-0.083333,"L":-0.025641,"P":-0.057692,"Q":-0.032051,"R":-0.064103,"S":-0.012821,"T":-0.076923,"V":-0.083333,"W":-0.076923,"X":-0.057692,"Y":-0.134615,"Z":-0.012821,"_":-0.025641,"a":-0.012821,"b":-0.012821,"c":-0.038462,"f":-0.044872,"k":-0.070513,"n":-0.025641,"p":-0.012821,"r":-0.064103,"s":-0.032051,"t":-0.032051,"u":-0.006410,"v":-0.057692,"x":-0.051282,"z":-0.012821},"s0":0.534180,"s1":0.640625,"t0":0.800781,"t1":0.708008},"p":{"advance_x":0.379000,"bbox_height":0.742851,"bbox_width":0.507844,"bearing_x":-0.057292,"bearing_y":0.528045,"charcode":"p","kernings":{"\"":-0.012821,"&":-0.006410,"(":-0.012821,"\/":-0.070513,"C":-0.012821,"F":-0.096154,"K":-0.044872,"S":-0.025641,"T":-0.070513,"V":-0.051282,"W":-0.044872,"X":-0.025641,"Y":-0.115385,"k":-0.025641,"r":-0.012821,"t":-0.025641,"x":-0.025641},"s0":0.078125,"s1":0.155273,"t0":0.809570,"t1":0.697266},"q":{"advance_x":0.387000,"bbox_height":0.798847,"bbox_width":0.513847,"bearing_x":-0.070112,"bearing_y":0.531250,"charcode":"q","kernings":{"\"":-0.108974,"&":-0.025641,"(":-0.083333,"\/":-0.064103,"B":-0.032051,"C":-0.044872,"E":-0.070513,"F":-0.083333,"K":-0.102564,"L":-0.064103,"P":-0.038462,"Q":-0.012821,"R":-0.051282,"S":-0.025641,"T":-0.083333,"V":-0.083333,"W":-0.070513,"X":-0.102564,"Y":-0.134615,"Z":-0.032051,"\\":-0.025641,"_":-0.134615,"a":-0.032051,"c":-0.032051,"d":-0.012821,"f":-0.032051,"g":-0.012821,"k":-0.070513,"m":-0.012821,"n":-0.032051,"r":-0.057692,"s":-0.025641,"t":-0.070513,"u":-0.012821,"v":-0.057692,"x":-0.044872,"z":-0.006410},"s0":0.394531,"s1":0.472656,"t0":0.842773,"t1":0.721680},"r":{"advance_x":0.352001,"bbox_height":0.614846,"bbox_width":0.465845,"bearing_x":-0.057292,"bearing_y":0.529247,"charcode":"r","kernings":{"\/":-0.044872,"B":-0.012821,"C":-0.012821,"F":-0.076923,"K":-0.044872,"S":-0.025641,"T":-0.070513,"X":-0.012821,"Y":-0.102564,"b":-0.006410,"k":-0.025641,"o":-0.006410,"r":-0.012821,"t":-0.032051,"x":-0.012821},"s0":0,"s1":0.070312,"t0":0.824219,"t1":0.730469},"s":{"advance_x":0.365998,"bbox_height":0.633845,"bbox_width":0.479843,"bearing_x":-0.057292,"bearing_y":0.525240,"charcode":"s","kernings":{"\"":-0.102564,"(":-0.012821,"\/":-0.076923,"B":-0.038462,"C":-0.051282,"F":-0.102564,"K":-0.025641,"O":-0.006410,"P":-0.044872,"Q":-0.032051,"S":-0.032051,"T":-0.076923,"V":-0.076923,"W":-0.083333,"X":-0.012821,"Y":-0.134615,"b":-0.032051,"e":-0.025641,"f":-0.032051,"k":-0.032051,"o":-0.006410,"p":-0.025641,"r":-0.057692,"s":-0.025641,"t":-0.006410,"v":-0.044872,"x":-0.032051},"s0":0.155273,"s1":0.227539,"t0":0.830078,"t1":0.734375},"t":{"advance_x":0.297000,"bbox_height":0.806847,"bbox_width":0.427847,"bearing_x":-0.074119,"bearing_y":0.713141,"charcode":"t","kernings":{"&":-0.038462,"C":-0.032051,"E":-0.025641,"F":-0.012821,"L":-0.025641,"X":-0.032051,"Y":-0.025641,"_":-0.057692,"k":-0.025641,"n":-0.025641,"r":-0.012821,"t":-0.032051,"x":-0.032051},"s0":0.227539,"s1":0.291992,"t0":0.863281,"t1":0.741211},"u":{"advance_x":0.446001,"bbox_height":0.560841,"bbox_width":0.621845,"bearing_x":-0.118990,"bearing_y":0.497196,"charcode":"u","kernings":{"\"":-0.064103,"&":-0.032051,"(":-0.038462,"\/":-0.064103,"B":-0.025641,"C":-0.025641,"E":-0.032051,"F":-0.076923,"K":-0.064103,"L":-0.025641,"P":-0.025641,"R":-0.038462,"S":-0.032051,"T":-0.076923,"V":-0.070513,"W":-0.057692,"X":-0.064103,"Y":-0.134615,"a":-0.025641,"c":-0.025641,"g":-0.012821,"k":-0.044872,"r":-0.038462,"t":-0.025641,"v":-0.032051,"x":-0.032051},"s0":0.291992,"s1":0.386719,"t0":0.833984,"t1":0.749023},"v":{"advance_x":0.450001,"bbox_height":0.563846,"bbox_width":0.563846,"bearing_x":-0.057292,"bearing_y":0.515224,"charcode":"v","kernings":{"\"":-0.038462,"&":-0.064103,"(":-0.076923,"-":-0.044872,"\/":-0.032051,"@":-0.006410,"A":-0.038462,"B":-0.012821,"C":-0.076923,"D":-0.025641,"E":-0.076923,"F":-0.102564,"G":-0.038462,"K":-0.108974,"L":-0.102564,"O":-0.025641,"P":-0.006410,"Q":-0.025641,"R":-0.032051,"S":-0.064103,"T":-0.083333,"V":-0.064103,"W":-0.044872,"X":-0.102564,"Y":-0.115385,"Z":-0.057692,"\\":-0.057692,"_":-0.115385,"a":-0.044872,"b":-0.070513,"c":-0.032051,"d":-0.025641,"e":-0.044872,"f":-0.025641,"g":-0.038462,"h":-0.044872,"j":-0.032051,"k":-0.032051,"m":-0.044872,"n":-0.076923,"o":-0.051282,"p":-0.038462,"r":-0.038462,"s":-0.025641,"t":-0.064103,"u":-0.044872,"v":-0.032051,"w":-0.025641,"x":-0.012821,"y":-0.006410},"s0":0.640625,"s1":0.726562,"t0":0.843750,"t1":0.757812},"w":{"advance_x":0.580998,"bbox_height":0.553849,"bbox_width":0.759847,"bearing_x":-0.106971,"bearing_y":0.477163,"charcode":"w","kernings":{"\"":-0.051282,"&":-0.012821,"(":-0.032051,"\/":-0.038462,"B":-0.032051,"C":-0.006410,"F":-0.096154,"K":-0.064103,"P":-0.025641,"R":-0.032051,"T":-0.070513,"V":-0.070513,"W":-0.070513,"X":-0.032051,"Y":-0.134615,"\\":-0.025641,"_":-0.012821,"a":-0.012821,"k":-0.038462,"r":-0.012821,"t":-0.025641,"v":-0.032051,"x":-0.025641},"s0":0.817383,"s1":0.932617,"t0":0.863281,"t1":0.779297},"x":{"advance_x":0.455998,"bbox_height":0.553849,"bbox_width":0.569843,"bearing_x":-0.057292,"bearing_y":0.477163,"charcode":"x","kernings":{"\"":-0.070513,"&":-0.044872,"(":-0.032051,"-":-0.064103,"\/":-0.038462,"A":-0.025641,"C":-0.064103,"F":-0.102564,"G":-0.032051,"K":-0.044872,"L":-0.012821,"N":-0.006410,"O":-0.038462,"P":-0.012821,"Q":-0.044872,"R":-0.012821,"S":-0.051282,"T":-0.083333,"U":-0.025641,"V":-0.070513,"Y":-0.115385,"Z":-0.038462,"a":-0.025641,"b":-0.070513,"c":-0.012821,"d":-0.032051,"e":-0.038462,"g":-0.032051,"h":-0.025641,"j":-0.025641,"k":-0.038462,"m":-0.012821,"n":-0.006410,"o":-0.064103,"p":-0.057692,"r":-0.012821,"s":-0.038462,"t":-0.032051,"u":-0.025641,"v":-0.032051,"w":-0.032051,"x":-0.025641,"y":-0.012821},"s0":0.726562,"s1":0.813477,"t0":0.867188,"t1":0.783203},"y":{"advance_x":0.408003,"bbox_height":0.771847,"bbox_width":0.631842,"bearing_x":-0.098958,"bearing_y":0.495192,"charcode":"y","kernings":{"\"":-0.070513,"&":-0.032051,"(":-0.057692,"\/":-0.057692,"B":-0.032051,"C":-0.032051,"E":-0.044872,"F":-0.076923,"K":-0.076923,"L":-0.032051,"P":-0.038462,"R":-0.044872,"S":-0.025641,"T":-0.083333,"V":-0.070513,"W":-0.076923,"X":-0.070513,"Y":-0.134615,"_":-0.051282,"a":-0.025641,"b":-0.012821,"c":-0.012821,"d":-0.006410,"f":-0.032051,"k":-0.057692,"n":-0.025641,"p":-0.006410,"r":-0.038462,"s":-0.025641,"t":-0.057692,"v":-0.032051,"x":-0.057692},"s0":0.472656,"s1":0.568359,"t0":0.917969,"t1":0.800781},"z":{"advance_x":0.348001,"bbox_height":0.536846,"bbox_width":0.461845,"bearing_x":-0.057292,"bearing_y":0.469952,"charcode":"z","kernings":{"\"":-0.057692,"&":-0.006410,"\/":-0.038462,"B":-0.038462,"F":-0.096154,"K":-0.038462,"P":-0.025641,"Q":0.006410,"R":-0.025641,"S":-0.038462,"T":-0.070513,"V":-0.070513,"W":-0.064103,"Y":-0.115385,"b":-0.025641,"e":-0.012821,"f":-0.025641,"k":-0.012821,"o":-0.025641,"p":-0.025641,"r":-0.032051,"s":-0.006410,"t":-0.012821,"v":-0.038462,"w":-0.012821},"s0":0.568359,"s1":0.638672,"t0":0.881836,"t1":0.800781},"{":{"advance_x":0.264999,"bbox_height":0.834842,"bbox_width":0.408842,"bearing_x":-0.086939,"bearing_y":0.731971,"charcode":"{","kernings":{},"s0":0.938477,"s1":1,"t0":0.813477,"t1":0.686523},"|":{"advance_x":0.137000,"bbox_height":0.837847,"bbox_width":0.250845,"bearing_x":-0.057292,"bearing_y":0.761218,"charcode":"|","kernings":{},"s0":0.070312,"s1":0.108398,"t0":0.936523,"t1":0.809570},"}":{"advance_x":0.264999,"bbox_height":0.834842,"bbox_width":0.408848,"bearing_x":-0.057292,"bearing_y":0.731971,"charcode":"}","kernings":{},"s0":0.932617,"s1":0.994141,"t0":0.940430,"t1":0.813477},"~":{"advance_x":0.501997,"bbox_height":0.362843,"bbox_width":0.615848,"bearing_x":-0.057292,"bearing_y":0.455128,"charcode":"~","kernings":{},"s0":0.108398,"s1":0.202148,"t0":0.884766,"t1":0.830078},"©":{"advance_x":0.337002,"bbox_height":0.475843,"bbox_width":0.585844,"bearing_x":-0.122997,"bearing_y":0.811298,"charcode":"©","kernings":{},"s0":0.813477,"s1":0.902344,"t0":0.935547,"t1":0.863281},"‘":{"advance_x":0.176000,"bbox_height":0.378850,"bbox_width":0.313846,"bearing_x":-0.058093,"bearing_y":0.804087,"charcode":"‘","kernings":{},"s0":0,"s1":0.047852,"t0":0.881836,"t1":0.824219},"’":{"advance_x":0.176000,"bbox_height":0.378850,"bbox_width":0.313846,"bearing_x":-0.080128,"bearing_y":0.782051,"charcode":"’","kernings":{},"s0":0.712891,"s1":0.760742,"t0":0.924805,"t1":0.867188},"“":{"advance_x":0.353998,"bbox_height":0.378850,"bbox_width":0.491849,"bearing_x":-0.058093,"bearing_y":0.804087,"charcode":"“","kernings":{},"s0":0.638672,"s1":0.712891,"t0":0.901367,"t1":0.843750},"”":{"advance_x":0.353998,"bbox_height":0.378850,"bbox_width":0.491843,"bearing_x":-0.080128,"bearing_y":0.782051,"charcode":"”","kernings":{},"s0":0.202148,"s1":0.276367,"t0":0.920898,"t1":0.863281},"…":{"advance_x":0.443998,"bbox_height":0.258845,"bbox_width":0.557843,"bearing_x":-0.057292,"bearing_y":0.181090,"charcode":"…","kernings":{},"s0":0.291992,"s1":0.376953,"t0":0.873047,"t1":0.833984},"€":{"advance_x":0.508000,"bbox_height":0.897843,"bbox_width":0.621845,"bearing_x":-0.057292,"bearing_y":0.713141,"charcode":"€","kernings":{},"s0":0.376953,"s1":0.471680,"t0":0.979492,"t1":0.842773}},"height":1.115385,"max_advance":1.346154,"name":"crocodile_feet","size":156,"space_advance":0.219952} -------------------------------------------------------------------------------- /Shared/Font/crocodile_feet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shipyard-games/SCNText2D/88f0b4da36072e6a9537b88eab54df9b5f3893cb/Shared/Font/crocodile_feet.png -------------------------------------------------------------------------------- /Shared/FontMetrics.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FontMetrics.swift 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | class FontMetrics: Codable { 11 | 12 | enum CodingKeys: String, CodingKey { 13 | case ascender 14 | case descender 15 | case glyphData = "glyph_data" 16 | case height 17 | case maxAdvance = "max_advance" 18 | case name 19 | case size 20 | case spaceAdvance = "space_advance" 21 | } 22 | 23 | var ascender: Float 24 | var descender: Float 25 | var glyphData: [String : GlyphData] 26 | var height: Float 27 | var maxAdvance: Float 28 | var name: String 29 | var size: Int 30 | var spaceAdvance: Float 31 | } 32 | -------------------------------------------------------------------------------- /Shared/GlyphData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GlyphData.swift 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import Foundation 9 | 10 | class GlyphData: Codable { 11 | 12 | enum CodingKeys: String, CodingKey { 13 | case advanceX = "advance_x" 14 | case bboxHeight = "bbox_height" 15 | case bboxWidth = "bbox_width" 16 | case bearingX = "bearing_x" 17 | case bearingY = "bearing_y" 18 | case charcode 19 | case kernings 20 | case s0 21 | case s1 22 | case t0 23 | case t1 24 | } 25 | 26 | var advanceX: Float 27 | var bboxHeight: Float 28 | var bboxWidth: Float 29 | var bearingX: Float 30 | var bearingY: Float 31 | var charcode: String 32 | var kernings: [String : Float] 33 | var s0: Float 34 | var s1: Float 35 | var t0: Float 36 | var t1: Float 37 | } 38 | -------------------------------------------------------------------------------- /Shared/SCNText2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SCNText2D.swift 3 | // SCNText2D 4 | // 5 | // Created by Teemu Harju on 10/02/2019. 6 | // 7 | 8 | import Foundation 9 | import SceneKit 10 | import Metal 11 | import MetalKit 12 | 13 | public class SCNText2D { 14 | 15 | public struct SDFParams { 16 | let smoothing: Float 17 | let fontWidth: Float 18 | let outlineWidth: Float 19 | let shadowWidth: Float 20 | let shadowOffset: float2 21 | let fontColor: float4 22 | let outlineColor: float4 23 | let shadowColor: float4 24 | 25 | public init(smoothing: Float, fontWidth: Float, outlineWidth: Float, shadowWidth: Float, shadowOffset: float2, fontColor: float4, outlineColor: float4, shadowColor: float4) { 26 | self.smoothing = smoothing 27 | self.fontWidth = fontWidth 28 | self.outlineWidth = outlineWidth 29 | self.shadowWidth = shadowWidth 30 | self.shadowOffset = shadowOffset 31 | self.fontColor = fontColor 32 | self.outlineColor = outlineColor 33 | self.shadowColor = shadowColor 34 | } 35 | } 36 | 37 | private struct Vertex { 38 | var x, y, z: Float 39 | var u, v: Float 40 | } 41 | 42 | public typealias Color = float4 43 | 44 | public enum TextAlignment { 45 | case left 46 | case right 47 | case centered 48 | } 49 | 50 | private static let library: MTLLibrary = { 51 | guard let device = MTLCreateSystemDefaultDevice() else { 52 | fatalError( "Failed to get the system's default Metal device." ) 53 | } 54 | let shaderLibraryUrl = Bundle(for: SCNText2D.self).url(forResource: "SCNText2D-Shaders", withExtension: "metallib")! 55 | return try! device.makeLibrary(URL: shaderLibraryUrl) 56 | }() 57 | 58 | private static var textureCache = [String: MTLTexture]() 59 | private static var metricsCache = [String: FontMetrics]() 60 | private static var atlasCache = [String: AtlasData]() 61 | private static var materialCache = [String: SCNMaterial]() 62 | 63 | public static func load(font fontName: String, bundle: Bundle, fontConfig: SDFParams) { 64 | guard let device = MTLCreateSystemDefaultDevice() else { 65 | fatalError( "Failed to get the system's default Metal device." ) 66 | } 67 | 68 | SCNText2D.loadFontMetrics(for: fontName, bundle: bundle) 69 | SCNText2D.loadTexture(for: fontName, bundle: bundle, using: device) 70 | SCNText2D.loadAtlasData(for: fontName, bundle: bundle) 71 | 72 | let shaderProgram = SCNProgram() 73 | shaderProgram.vertexFunctionName = "sdfTextVertex" 74 | 75 | switch (fontConfig.outlineColor[3], fontConfig.shadowColor[3]) { 76 | case (_, let shadow) where shadow > 0.0: 77 | shaderProgram.fragmentFunctionName = "sdfTextOutlineShadowFragment" 78 | 79 | case (let outline, _) where outline > 0.0: 80 | shaderProgram.fragmentFunctionName = "sdfTextOutlineFragment" 81 | 82 | default: 83 | shaderProgram.fragmentFunctionName = "sdfTextFragment" 84 | } 85 | 86 | shaderProgram.isOpaque = false 87 | shaderProgram.library = library 88 | 89 | guard let texture = textureCache[fontName] else { 90 | fatalError("Font '\(fontName)' not loaded. No texture found.") 91 | } 92 | 93 | var fontConfig = fontConfig 94 | 95 | let textureMaterialProperty = SCNMaterialProperty(contents: texture) 96 | 97 | let fontConfigData = Data(bytes: &fontConfig, count: MemoryLayout.size) 98 | 99 | let material = SCNMaterial() 100 | material.name = "SDFText2D::\(fontName)" 101 | material.program = shaderProgram 102 | material.setValue(textureMaterialProperty, forKey: "fontTexture") 103 | material.setValue(fontConfigData, forKey: "params") 104 | 105 | SCNText2D.materialCache[fontName] = material 106 | } 107 | 108 | public static func create(from string: String, withFontNamed fontName: String, scale: Float = 1.0, lineSpacing: Float = 1.0, alignment: TextAlignment = .centered) -> SCNGeometry { 109 | guard let fontMetrics = SCNText2D.metricsCache[fontName] else { 110 | fatalError("Font '\(fontName)' not loaded. No font metrics found.") 111 | } 112 | 113 | guard let atlasData = SCNText2D.atlasCache[fontName] else { 114 | fatalError("Font '\(fontName)' not loaded. No atlas data found.") 115 | } 116 | 117 | let geometry = buildGeometry(string, fontMetrics, atlasData, alignment, scale, lineSpacing) 118 | if let material = SCNText2D.materialCache[fontName] { 119 | geometry.materials = [material] 120 | } 121 | return geometry 122 | } 123 | 124 | public static func clone(fontNamed fontName: String, toFontNamed newFontName: String, using fontConfig: SDFParams) { 125 | guard let texture = textureCache[fontName], let metrics = metricsCache[fontName], 126 | let atlas = atlasCache[fontName], let material = materialCache[fontName] else { 127 | fatalError("Trying to clone a font that does not exist. fontName=\(fontName)") 128 | } 129 | 130 | // Use same texture, metrics and atlas for new font 131 | textureCache[newFontName] = texture 132 | metricsCache[newFontName] = metrics 133 | atlasCache[newFontName] = atlas 134 | 135 | // Create new material using the new font config. 136 | guard let newMaterial = material.copy() as? SCNMaterial else { 137 | fatalError("Failed to copy material.") 138 | } 139 | 140 | newMaterial.program = SCNProgram() 141 | newMaterial.program?.library = library 142 | newMaterial.program?.vertexFunctionName = "sdfTextVertex" 143 | newMaterial.program?.isOpaque = false 144 | 145 | switch (fontConfig.outlineColor[3], fontConfig.shadowColor[3]) { 146 | case (_, let shadow) where shadow > 0.0: 147 | newMaterial.program?.fragmentFunctionName = "sdfTextOutlineShadowFragment" 148 | 149 | case (let outline, _) where outline > 0.0: 150 | newMaterial.program?.fragmentFunctionName = "sdfTextOutlineFragment" 151 | 152 | default: 153 | newMaterial.program?.fragmentFunctionName = "sdfTextFragment" 154 | } 155 | 156 | var fontConfig = fontConfig 157 | let fontConfigData = Data(bytes: &fontConfig, count: MemoryLayout.size) 158 | 159 | newMaterial.setValue(fontConfigData, forKey: "params") 160 | 161 | materialCache[newFontName] = newMaterial 162 | } 163 | 164 | private static func buildGeometry(_ string: String, _ fontMetrics: FontMetrics, _ atlasData: AtlasData, _ alignment: TextAlignment, _ scale: Float, _ lineSpacing: Float) -> SCNGeometry { 165 | 166 | let lines = string.unicodeScalars.split(separator: Unicode.Scalar("\n")) 167 | 168 | let textureWidth = atlasData.meta.width 169 | let textureHeight = atlasData.meta.height 170 | 171 | var cursorX: Float = 0.0 172 | var cursorY: Float = 0.0 173 | 174 | var vertices = [Vertex]() 175 | 176 | var lineVertices = [Vertex]() 177 | 178 | var indices = [UInt16]() 179 | 180 | var minX: Float = Float.infinity 181 | var minY: Float = Float.infinity 182 | var maxX: Float = -Float.infinity 183 | var maxY: Float = -Float.infinity 184 | 185 | for line in lines { 186 | var lineMaxYOffset: Float = -Float.infinity 187 | for (i, char) in line.enumerated() { 188 | guard let glyph = fontMetrics.glyphData["\(char)"] else { 189 | cursorX += fontMetrics.spaceAdvance * scale 190 | continue 191 | } 192 | 193 | let uvKey = String(format: "0x%04X", char.value).lowercased() 194 | guard let uvData = atlasData.frames[uvKey] else { 195 | fatalError("No UV-coordinates for character '\(char)'!") 196 | } 197 | 198 | if (i > 0) { 199 | let strIndex = string.index(string.startIndex, offsetBy: i - 1) 200 | let kernChar = String(string[strIndex]) 201 | let kernVal = glyph.kernings[kernChar] ?? 0.0 202 | if (kernVal != 0.0 && (kernVal < -0.001 || kernVal > 0.001)) { 203 | cursorX += kernVal * scale; 204 | } 205 | } 206 | 207 | let glyphWidth = glyph.bboxWidth * scale; 208 | let glyphHeight = glyph.bboxHeight * scale; 209 | let glyphBearingX = glyph.bearingX * scale; 210 | let glyphBearingY = glyph.bearingY * scale; 211 | let glyphAdvanceX = glyph.advanceX * scale; 212 | 213 | let x = cursorX + glyphBearingX; 214 | let y = cursorY + glyphBearingY; 215 | let z = Float(i) * 0.001 216 | 217 | let lineYOffset = glyphBearingY - glyphHeight 218 | 219 | if lineYOffset < 0.0 { // below baseline 220 | if lineYOffset < lineMaxYOffset { 221 | lineMaxYOffset = lineYOffset 222 | } 223 | } 224 | 225 | if y > maxY { maxY = y} 226 | if x < minX { minX = x } 227 | 228 | if (y - glyphHeight) < minY { minY = y - glyphHeight } 229 | if (x + glyphWidth) > maxX { maxX = x + glyphWidth } 230 | 231 | let w = uvData["w"]! / textureWidth 232 | let h = uvData["h"]! / textureHeight 233 | let s0 = uvData["x"]! / textureWidth 234 | let t0 = uvData["y"]! / textureHeight 235 | let s1 = s0 + w 236 | let t1 = t0 + h 237 | 238 | let v1 = Vertex(x: x, y: y - glyphHeight, z: z, u: s0, v: t1) 239 | let v2 = Vertex(x: x + glyphWidth, y: y - glyphHeight, z: z, u: s1, v: t1) 240 | let v3 = Vertex(x: x, y: y, z: z, u: s0, v: t0) 241 | let v4 = Vertex(x: x + glyphWidth, y: y, z: z, u: s1, v: t0) 242 | 243 | lineVertices.append(v1) 244 | lineVertices.append(v2) 245 | lineVertices.append(v3) 246 | lineVertices.append(v4) 247 | 248 | let curidx = UInt16(vertices.count + i * 4) 249 | indices.append(curidx + 0) 250 | indices.append(curidx + 1) 251 | indices.append(curidx + 2) // first triangle 252 | indices.append(curidx + 1) 253 | indices.append(curidx + 3) 254 | indices.append(curidx + 2) // second triangle 255 | 256 | cursorX += glyphAdvanceX 257 | } 258 | 259 | cursorY -= fontMetrics.height * scale * lineSpacing 260 | 261 | alignLine(&lineVertices, withAlignment: alignment, lineWidth: cursorX) 262 | 263 | vertices.append(contentsOf: lineVertices) 264 | 265 | cursorX = 0 266 | lineVertices = [] 267 | } 268 | 269 | // Center align the vertices vertically 270 | let width = maxX - minX 271 | vertices = vertices.map { 272 | (vertex: Vertex) in 273 | var vertex = vertex 274 | switch (alignment) { 275 | case .centered: 276 | break // already aligned per line 277 | case .left: 278 | vertex.x -= width / 2 279 | case .right: 280 | vertex.x += width / 2 281 | } 282 | return vertex 283 | } 284 | 285 | let indicesData = Data(bytes: &indices, count: MemoryLayout.size * indices.count) 286 | let element = SCNGeometryElement(data: indicesData, primitiveType: .triangles, primitiveCount: indices.count / 3, bytesPerIndex: MemoryLayout.size) 287 | 288 | let verticesData = Data(bytes: &vertices, count: MemoryLayout.size * vertices.count) 289 | 290 | let vertexSource = SCNGeometrySource(data: verticesData, semantic: .vertex, vectorCount: vertices.count, 291 | usesFloatComponents: true, componentsPerVector: 3, 292 | bytesPerComponent: MemoryLayout.size, dataOffset: 0, 293 | dataStride: MemoryLayout.size) 294 | 295 | let uvSource = SCNGeometrySource(data: verticesData, semantic: .texcoord, vectorCount: vertices.count, 296 | usesFloatComponents: true, componentsPerVector: 2, 297 | bytesPerComponent: MemoryLayout.size, 298 | dataOffset: MemoryLayout.size * 3, 299 | dataStride: MemoryLayout.size) 300 | 301 | let geometry = SCNGeometry(sources: [vertexSource, uvSource], elements: [element]) 302 | 303 | return geometry 304 | } 305 | 306 | private static func alignLine(_ lineVertices: inout [Vertex], withAlignment alignment: TextAlignment, lineWidth: Float) { 307 | switch (alignment) { 308 | case .centered: 309 | lineVertices = lineVertices.map { 310 | (vertex: Vertex) -> Vertex in 311 | var vertex = vertex 312 | vertex.x -= lineWidth / 2 313 | return vertex 314 | } 315 | case .left: 316 | // we keep the lines first glyph starting at zero and center the geometry once it is complete 317 | break 318 | case .right: 319 | // we move the last glyphs position to zero so we can do right alignment once the geometry is complete 320 | lineVertices = lineVertices.map { 321 | (vertex: Vertex) -> Vertex in 322 | var vertex = vertex 323 | vertex.x -= lineWidth 324 | return vertex 325 | } 326 | } 327 | } 328 | 329 | private static func loadTexture(for fontNamed: String, bundle: Bundle, using device: MTLDevice) { 330 | let textureLoader = MTKTextureLoader(device: device) 331 | let textureLoaderOptions: [MTKTextureLoader.Option: Any] = [ 332 | .SRGB : false 333 | ] 334 | 335 | let mdlTexture = MDLTexture(named: "\(fontNamed).png", bundle: bundle)! 336 | let texture = try! textureLoader.newTexture(texture: mdlTexture, options: textureLoaderOptions) 337 | SCNText2D.textureCache[fontNamed] = texture 338 | } 339 | 340 | private static func loadFontMetrics(for fontNamed: String, bundle: Bundle) { 341 | let jsonURL = bundle.url(forResource: fontNamed, withExtension: "json")! 342 | let jsonData = try! Data(contentsOf: jsonURL) 343 | 344 | let metrics = try! JSONDecoder().decode(FontMetrics.self, from: jsonData) 345 | 346 | SCNText2D.metricsCache[fontNamed] = metrics 347 | } 348 | 349 | private static func loadAtlasData(for fontNamed: String, bundle: Bundle) { 350 | let atlasDataURL = bundle.url(forResource: fontNamed, withExtension: "plist")! 351 | 352 | let atlas = try! PropertyListDecoder().decode(AtlasData.self, from: Data(contentsOf: atlasDataURL)) 353 | 354 | SCNText2D.atlasCache[fontNamed] = atlas 355 | } 356 | } 357 | 358 | --------------------------------------------------------------------------------