├── .gitignore ├── README.md ├── appinfo.json ├── resources ├── fonts │ ├── readme.md │ └── visitor2.ttf └── images │ ├── background-minimal.png │ ├── background-none.png │ ├── background-simple.png │ ├── background.png │ ├── battery-0.png │ ├── battery-100.png │ ├── battery-25.png │ ├── battery-50.png │ ├── battery-75.png │ ├── battery-charge.png │ ├── big-0.png │ ├── big-1.png │ ├── big-2.png │ ├── big-3.png │ ├── big-4.png │ ├── big-5.png │ ├── big-6.png │ ├── big-7.png │ ├── big-8.png │ ├── big-9.png │ ├── big-battery-0.png │ ├── big-battery-100.png │ ├── big-battery-25.png │ ├── big-battery-50.png │ ├── big-battery-75.png │ ├── big-battery-charge.png │ ├── big-colon.png │ ├── big-divide.png │ ├── hand-hour.png │ ├── hand-minute - Copy.png │ ├── hand-minute-long.png │ ├── hand-minute.png │ ├── med-0.png │ ├── med-1.png │ ├── med-2.png │ ├── med-3.png │ ├── med-4.png │ ├── med-5.png │ ├── med-6.png │ ├── med-7.png │ ├── med-8.png │ ├── med-9.png │ ├── med-colon.png │ ├── med-divide.png │ ├── menu_icon.png │ ├── tiny-0.png │ ├── tiny-1.png │ ├── tiny-2.png │ ├── tiny-3.png │ ├── tiny-4.png │ ├── tiny-5.png │ ├── tiny-6.png │ ├── tiny-7.png │ ├── tiny-8.png │ ├── tiny-9.png │ ├── tiny-colon.png │ └── tiny-divide.png ├── server ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ └── bootstrap.min.css ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── index.html ├── index2.html ├── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ └── jquery.min.js └── manifest.appcache ├── src ├── Aviator.c ├── blur.c ├── effect_layer.c ├── effect_layer.h ├── effects.c ├── effects.h ├── js │ └── pebble-js-app.js ├── math.c └── math.h └── wscript /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | .lock-waf_darwin_build 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Aviator v2.0 2 | ============ 3 | 4 | Aviator Watchface for Pebble 2.0 by orviwan and Jnm. Based on a original design by ninthsrw01. 5 | 6 | Lots of configuration settings available via the Phone application. 7 | 8 |                9 | 10 | Features: 11 | 12 | - 12/24 hour time format 13 | - Show/Hide "Seconds" units (conserves battery) 14 | - Invert color scheme 15 | - Bluetooth vibration on disconnect 16 | - Vibration timer, configurable in Minutes. 17 | - Show/Hide clock face minute/hour hands 18 | - International/US date or Local/Timezone 19 | - Background - Full, Simple, Minimal, None 20 | - Battery status indicator (25%, 50%, 75%, 100%, Charging) 21 | - Big Mode (for those with poor eyesight) 22 | - User selectable secondary timezone 23 | -------------------------------------------------------------------------------- /appinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "appKeys": { 3 | "background": 6, 4 | "bigmode": 8, 5 | "bluetoothvibe": 2, 6 | "dayname": 10, 7 | "hands": 4, 8 | "invert": 1, 9 | "seconds": 0, 10 | "style": 5, 11 | "timezone": 9, 12 | "timezoneLabel": 11, 13 | "timezoneOffset": 7, 14 | "vibeminutes": 3 15 | }, 16 | "capabilities": [ 17 | "configurable" 18 | ], 19 | "companyName": "orviwan", 20 | "longName": "Aviator 2.1", 21 | "projectType": "native", 22 | "resources": { 23 | "media": [ 24 | { 25 | "file": "images/med-9.png", 26 | "name": "IMAGE_MED_9", 27 | "type": "png" 28 | }, 29 | { 30 | "file": "images/med-8.png", 31 | "name": "IMAGE_MED_8", 32 | "type": "png" 33 | }, 34 | { 35 | "file": "images/tiny-colon.png", 36 | "name": "IMAGE_TINY_COLON", 37 | "type": "png" 38 | }, 39 | { 40 | "file": "images/tiny-7.png", 41 | "name": "IMAGE_TINY_7", 42 | "type": "png" 43 | }, 44 | { 45 | "file": "images/battery-100.png", 46 | "name": "IMAGE_BATTERY_100", 47 | "type": "png" 48 | }, 49 | { 50 | "file": "images/tiny-2.png", 51 | "name": "IMAGE_TINY_2", 52 | "type": "png" 53 | }, 54 | { 55 | "file": "images/big-battery-50.png", 56 | "name": "IMAGE_BIG_BATTERY_50", 57 | "type": "png" 58 | }, 59 | { 60 | "file": "images/background.png", 61 | "name": "IMAGE_BACKGROUND", 62 | "type": "png" 63 | }, 64 | { 65 | "file": "images/big-battery-75.png", 66 | "name": "IMAGE_BIG_BATTERY_75", 67 | "type": "png" 68 | }, 69 | { 70 | "file": "images/background-simple.png", 71 | "name": "IMAGE_BACKGROUND_SIMPLE", 72 | "type": "png" 73 | }, 74 | { 75 | "file": "images/big-6.png", 76 | "name": "IMAGE_BIG_6", 77 | "type": "png" 78 | }, 79 | { 80 | "file": "images/battery-75.png", 81 | "name": "IMAGE_BATTERY_75", 82 | "type": "png" 83 | }, 84 | { 85 | "file": "images/med-5.png", 86 | "name": "IMAGE_MED_5", 87 | "type": "png" 88 | }, 89 | { 90 | "file": "images/big-colon.png", 91 | "name": "IMAGE_BIG_COLON", 92 | "type": "png" 93 | }, 94 | { 95 | "file": "images/hand-minute.png", 96 | "name": "IMAGE_HAND_MINUTE", 97 | "type": "png" 98 | }, 99 | { 100 | "file": "images/battery-25.png", 101 | "name": "IMAGE_BATTERY_25", 102 | "type": "png" 103 | }, 104 | { 105 | "file": "images/big-4.png", 106 | "name": "IMAGE_BIG_4", 107 | "type": "png" 108 | }, 109 | { 110 | "file": "images/tiny-8.png", 111 | "name": "IMAGE_TINY_8", 112 | "type": "png" 113 | }, 114 | { 115 | "file": "images/tiny-1.png", 116 | "name": "IMAGE_TINY_1", 117 | "type": "png" 118 | }, 119 | { 120 | "file": "images/background-none.png", 121 | "name": "IMAGE_BACKGROUND_NONE", 122 | "type": "png" 123 | }, 124 | { 125 | "file": "images/tiny-9.png", 126 | "name": "IMAGE_TINY_9", 127 | "type": "png" 128 | }, 129 | { 130 | "file": "images/battery-50.png", 131 | "name": "IMAGE_BATTERY_50", 132 | "type": "png" 133 | }, 134 | { 135 | "file": "images/big-battery-25.png", 136 | "name": "IMAGE_BIG_BATTERY_25", 137 | "type": "png" 138 | }, 139 | { 140 | "file": "images/big-5.png", 141 | "name": "IMAGE_BIG_5", 142 | "type": "png" 143 | }, 144 | { 145 | "file": "images/tiny-0.png", 146 | "name": "IMAGE_TINY_0", 147 | "type": "png" 148 | }, 149 | { 150 | "file": "images/background-minimal.png", 151 | "name": "IMAGE_BACKGROUND_MINIMAL", 152 | "type": "png" 153 | }, 154 | { 155 | "file": "images/big-battery-100.png", 156 | "name": "IMAGE_BIG_BATTERY_100", 157 | "type": "png" 158 | }, 159 | { 160 | "file": "images/big-1.png", 161 | "name": "IMAGE_BIG_1", 162 | "type": "png" 163 | }, 164 | { 165 | "file": "images/big-8.png", 166 | "name": "IMAGE_BIG_8", 167 | "type": "png" 168 | }, 169 | { 170 | "file": "images/tiny-5.png", 171 | "name": "IMAGE_TINY_5", 172 | "type": "png" 173 | }, 174 | { 175 | "file": "images/med-0.png", 176 | "name": "IMAGE_MED_0", 177 | "type": "png" 178 | }, 179 | { 180 | "file": "images/tiny-3.png", 181 | "name": "IMAGE_TINY_3", 182 | "type": "png" 183 | }, 184 | { 185 | "file": "images/med-4.png", 186 | "name": "IMAGE_MED_4", 187 | "type": "png" 188 | }, 189 | { 190 | "file": "images/big-battery-charge.png", 191 | "name": "IMAGE_BIG_BATTERY_CHARGE", 192 | "type": "png" 193 | }, 194 | { 195 | "file": "images/battery-charge.png", 196 | "name": "IMAGE_BATTERY_CHARGE", 197 | "type": "png" 198 | }, 199 | { 200 | "file": "images/big-7.png", 201 | "name": "IMAGE_BIG_7", 202 | "type": "png" 203 | }, 204 | { 205 | "file": "images/menu_icon.png", 206 | "menuIcon": true, 207 | "name": "IMAGE_MENU_ICON", 208 | "type": "png" 209 | }, 210 | { 211 | "file": "images/big-3.png", 212 | "name": "IMAGE_BIG_3", 213 | "type": "png" 214 | }, 215 | { 216 | "file": "images/big-0.png", 217 | "name": "IMAGE_BIG_0", 218 | "type": "png" 219 | }, 220 | { 221 | "file": "images/med-2.png", 222 | "name": "IMAGE_MED_2", 223 | "type": "png" 224 | }, 225 | { 226 | "file": "images/big-2.png", 227 | "name": "IMAGE_BIG_2", 228 | "type": "png" 229 | }, 230 | { 231 | "file": "images/hand-hour.png", 232 | "name": "IMAGE_HAND_HOUR", 233 | "type": "png" 234 | }, 235 | { 236 | "file": "images/med-1.png", 237 | "name": "IMAGE_MED_1", 238 | "type": "png" 239 | }, 240 | { 241 | "characterRegex": "[:0-9A-Z. -+]", 242 | "file": "fonts/visitor2.ttf", 243 | "name": "TINY_12", 244 | "type": "font" 245 | }, 246 | { 247 | "file": "images/big-9.png", 248 | "name": "IMAGE_BIG_9", 249 | "type": "png" 250 | }, 251 | { 252 | "file": "images/tiny-6.png", 253 | "name": "IMAGE_TINY_6", 254 | "type": "png" 255 | }, 256 | { 257 | "file": "images/med-7.png", 258 | "name": "IMAGE_MED_7", 259 | "type": "png" 260 | }, 261 | { 262 | "file": "images/big-battery-0.png", 263 | "name": "IMAGE_BIG_BATTERY_0", 264 | "type": "png" 265 | }, 266 | { 267 | "file": "images/tiny-divide.png", 268 | "name": "IMAGE_TINY_DIVIDE", 269 | "type": "png" 270 | }, 271 | { 272 | "file": "images/med-divide.png", 273 | "name": "IMAGE_MED_DIVIDE", 274 | "type": "png" 275 | }, 276 | { 277 | "file": "images/med-3.png", 278 | "name": "IMAGE_MED_3", 279 | "type": "png" 280 | }, 281 | { 282 | "file": "images/tiny-4.png", 283 | "name": "IMAGE_TINY_4", 284 | "type": "png" 285 | }, 286 | { 287 | "file": "images/med-colon.png", 288 | "name": "IMAGE_MED_COLON", 289 | "type": "png" 290 | }, 291 | { 292 | "file": "images/med-6.png", 293 | "name": "IMAGE_MED_6", 294 | "type": "png" 295 | }, 296 | { 297 | "file": "images/battery-0.png", 298 | "name": "IMAGE_BATTERY_0", 299 | "type": "png" 300 | }, 301 | { 302 | "file": "images/big-divide.png", 303 | "name": "IMAGE_BIG_DIVIDE", 304 | "type": "png" 305 | } 306 | ] 307 | }, 308 | "sdkVersion": "3", 309 | "shortName": "Aviator 2.1", 310 | "targetPlatforms": [ 311 | "aplite", 312 | "basalt" 313 | ], 314 | "uuid": "1757a18e-0e30-4389-aeca-7f0ff1391e77", 315 | "versionLabel": "1.22", 316 | "watchapp": { 317 | "watchface": true 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /resources/fonts/readme.md: -------------------------------------------------------------------------------- 1 | The .ttf font file is not provided with the source code due to licencing. 2 | 3 | Please download the Visitor font and place visitor2.ttf in this folder before compiling. 4 | -------------------------------------------------------------------------------- /resources/fonts/visitor2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/fonts/visitor2.ttf -------------------------------------------------------------------------------- /resources/images/background-minimal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/background-minimal.png -------------------------------------------------------------------------------- /resources/images/background-none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/background-none.png -------------------------------------------------------------------------------- /resources/images/background-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/background-simple.png -------------------------------------------------------------------------------- /resources/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/background.png -------------------------------------------------------------------------------- /resources/images/battery-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-0.png -------------------------------------------------------------------------------- /resources/images/battery-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-100.png -------------------------------------------------------------------------------- /resources/images/battery-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-25.png -------------------------------------------------------------------------------- /resources/images/battery-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-50.png -------------------------------------------------------------------------------- /resources/images/battery-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-75.png -------------------------------------------------------------------------------- /resources/images/battery-charge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/battery-charge.png -------------------------------------------------------------------------------- /resources/images/big-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-0.png -------------------------------------------------------------------------------- /resources/images/big-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-1.png -------------------------------------------------------------------------------- /resources/images/big-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-2.png -------------------------------------------------------------------------------- /resources/images/big-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-3.png -------------------------------------------------------------------------------- /resources/images/big-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-4.png -------------------------------------------------------------------------------- /resources/images/big-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-5.png -------------------------------------------------------------------------------- /resources/images/big-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-6.png -------------------------------------------------------------------------------- /resources/images/big-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-7.png -------------------------------------------------------------------------------- /resources/images/big-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-8.png -------------------------------------------------------------------------------- /resources/images/big-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-9.png -------------------------------------------------------------------------------- /resources/images/big-battery-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-0.png -------------------------------------------------------------------------------- /resources/images/big-battery-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-100.png -------------------------------------------------------------------------------- /resources/images/big-battery-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-25.png -------------------------------------------------------------------------------- /resources/images/big-battery-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-50.png -------------------------------------------------------------------------------- /resources/images/big-battery-75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-75.png -------------------------------------------------------------------------------- /resources/images/big-battery-charge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-battery-charge.png -------------------------------------------------------------------------------- /resources/images/big-colon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-colon.png -------------------------------------------------------------------------------- /resources/images/big-divide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/big-divide.png -------------------------------------------------------------------------------- /resources/images/hand-hour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/hand-hour.png -------------------------------------------------------------------------------- /resources/images/hand-minute - Copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/hand-minute - Copy.png -------------------------------------------------------------------------------- /resources/images/hand-minute-long.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/hand-minute-long.png -------------------------------------------------------------------------------- /resources/images/hand-minute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/hand-minute.png -------------------------------------------------------------------------------- /resources/images/med-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-0.png -------------------------------------------------------------------------------- /resources/images/med-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-1.png -------------------------------------------------------------------------------- /resources/images/med-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-2.png -------------------------------------------------------------------------------- /resources/images/med-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-3.png -------------------------------------------------------------------------------- /resources/images/med-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-4.png -------------------------------------------------------------------------------- /resources/images/med-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-5.png -------------------------------------------------------------------------------- /resources/images/med-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-6.png -------------------------------------------------------------------------------- /resources/images/med-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-7.png -------------------------------------------------------------------------------- /resources/images/med-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-8.png -------------------------------------------------------------------------------- /resources/images/med-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-9.png -------------------------------------------------------------------------------- /resources/images/med-colon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-colon.png -------------------------------------------------------------------------------- /resources/images/med-divide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/med-divide.png -------------------------------------------------------------------------------- /resources/images/menu_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/menu_icon.png -------------------------------------------------------------------------------- /resources/images/tiny-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-0.png -------------------------------------------------------------------------------- /resources/images/tiny-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-1.png -------------------------------------------------------------------------------- /resources/images/tiny-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-2.png -------------------------------------------------------------------------------- /resources/images/tiny-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-3.png -------------------------------------------------------------------------------- /resources/images/tiny-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-4.png -------------------------------------------------------------------------------- /resources/images/tiny-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-5.png -------------------------------------------------------------------------------- /resources/images/tiny-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-6.png -------------------------------------------------------------------------------- /resources/images/tiny-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-7.png -------------------------------------------------------------------------------- /resources/images/tiny-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-8.png -------------------------------------------------------------------------------- /resources/images/tiny-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-9.png -------------------------------------------------------------------------------- /resources/images/tiny-colon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-colon.png -------------------------------------------------------------------------------- /resources/images/tiny-divide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/resources/images/tiny-divide.png -------------------------------------------------------------------------------- /server/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.2 by @fat and @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Designed and built with all the love in the world by @mdo and @fat. 7 | */ 8 | 9 | .btn-default, 10 | .btn-primary, 11 | .btn-success, 12 | .btn-info, 13 | .btn-warning, 14 | .btn-danger { 15 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 16 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 17 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 18 | } 19 | 20 | .btn-default:active, 21 | .btn-primary:active, 22 | .btn-success:active, 23 | .btn-info:active, 24 | .btn-warning:active, 25 | .btn-danger:active, 26 | .btn-default.active, 27 | .btn-primary.active, 28 | .btn-success.active, 29 | .btn-info.active, 30 | .btn-warning.active, 31 | .btn-danger.active { 32 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 33 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 34 | } 35 | 36 | .btn:active, 37 | .btn.active { 38 | background-image: none; 39 | } 40 | 41 | .btn-default { 42 | text-shadow: 0 1px 0 #fff; 43 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e0e0e0)); 44 | background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%); 45 | background-image: -moz-linear-gradient(top, #ffffff 0%, #e0e0e0 100%); 46 | background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%); 47 | background-repeat: repeat-x; 48 | border-color: #dbdbdb; 49 | border-color: #ccc; 50 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); 51 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 52 | } 53 | 54 | .btn-default:hover, 55 | .btn-default:focus { 56 | background-color: #e0e0e0; 57 | background-position: 0 -15px; 58 | } 59 | 60 | .btn-default:active, 61 | .btn-default.active { 62 | background-color: #e0e0e0; 63 | border-color: #dbdbdb; 64 | } 65 | 66 | .btn-primary { 67 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#2d6ca2)); 68 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 69 | background-image: -moz-linear-gradient(top, #428bca 0%, #2d6ca2 100%); 70 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); 71 | background-repeat: repeat-x; 72 | border-color: #2b669a; 73 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); 74 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 75 | } 76 | 77 | .btn-primary:hover, 78 | .btn-primary:focus { 79 | background-color: #2d6ca2; 80 | background-position: 0 -15px; 81 | } 82 | 83 | .btn-primary:active, 84 | .btn-primary.active { 85 | background-color: #2d6ca2; 86 | border-color: #2b669a; 87 | } 88 | 89 | .btn-success { 90 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#419641)); 91 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); 92 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #419641 100%); 93 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); 94 | background-repeat: repeat-x; 95 | border-color: #3e8f3e; 96 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); 97 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 98 | } 99 | 100 | .btn-success:hover, 101 | .btn-success:focus { 102 | background-color: #419641; 103 | background-position: 0 -15px; 104 | } 105 | 106 | .btn-success:active, 107 | .btn-success.active { 108 | background-color: #419641; 109 | border-color: #3e8f3e; 110 | } 111 | 112 | .btn-warning { 113 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#eb9316)); 114 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 115 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); 116 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); 117 | background-repeat: repeat-x; 118 | border-color: #e38d13; 119 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); 120 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 121 | } 122 | 123 | .btn-warning:hover, 124 | .btn-warning:focus { 125 | background-color: #eb9316; 126 | background-position: 0 -15px; 127 | } 128 | 129 | .btn-warning:active, 130 | .btn-warning.active { 131 | background-color: #eb9316; 132 | border-color: #e38d13; 133 | } 134 | 135 | .btn-danger { 136 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c12e2a)); 137 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 138 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c12e2a 100%); 139 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); 140 | background-repeat: repeat-x; 141 | border-color: #b92c28; 142 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); 143 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 144 | } 145 | 146 | .btn-danger:hover, 147 | .btn-danger:focus { 148 | background-color: #c12e2a; 149 | background-position: 0 -15px; 150 | } 151 | 152 | .btn-danger:active, 153 | .btn-danger.active { 154 | background-color: #c12e2a; 155 | border-color: #b92c28; 156 | } 157 | 158 | .btn-info { 159 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#2aabd2)); 160 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 161 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); 162 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); 163 | background-repeat: repeat-x; 164 | border-color: #28a4c9; 165 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); 166 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 167 | } 168 | 169 | .btn-info:hover, 170 | .btn-info:focus { 171 | background-color: #2aabd2; 172 | background-position: 0 -15px; 173 | } 174 | 175 | .btn-info:active, 176 | .btn-info.active { 177 | background-color: #2aabd2; 178 | border-color: #28a4c9; 179 | } 180 | 181 | .thumbnail, 182 | .img-thumbnail { 183 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 184 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 185 | } 186 | 187 | .dropdown-menu > li > a:hover, 188 | .dropdown-menu > li > a:focus { 189 | background-color: #e8e8e8; 190 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); 191 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 192 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 193 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 194 | background-repeat: repeat-x; 195 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 196 | } 197 | 198 | .dropdown-menu > .active > a, 199 | .dropdown-menu > .active > a:hover, 200 | .dropdown-menu > .active > a:focus { 201 | background-color: #357ebd; 202 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 203 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 204 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 205 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 206 | background-repeat: repeat-x; 207 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 208 | } 209 | 210 | .navbar-default { 211 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); 212 | background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 213 | background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 214 | background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); 215 | background-repeat: repeat-x; 216 | border-radius: 4px; 217 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 218 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 219 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 220 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 221 | } 222 | 223 | .navbar-default .navbar-nav > .active > a { 224 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f3f3f3)); 225 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 226 | background-image: -moz-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); 227 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); 228 | background-repeat: repeat-x; 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); 230 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); 231 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075); 232 | } 233 | 234 | .navbar-brand, 235 | .navbar-nav > li > a { 236 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); 237 | } 238 | 239 | .navbar-inverse { 240 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); 241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%); 242 | background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); 243 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); 244 | background-repeat: repeat-x; 245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); 247 | } 248 | 249 | .navbar-inverse .navbar-nav > .active > a { 250 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#222222), to(#282828)); 251 | background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%); 252 | background-image: -moz-linear-gradient(top, #222222 0%, #282828 100%); 253 | background-image: linear-gradient(to bottom, #222222 0%, #282828 100%); 254 | background-repeat: repeat-x; 255 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); 256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); 257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25); 258 | } 259 | 260 | .navbar-inverse .navbar-brand, 261 | .navbar-inverse .navbar-nav > li > a { 262 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 263 | } 264 | 265 | .navbar-static-top, 266 | .navbar-fixed-top, 267 | .navbar-fixed-bottom { 268 | border-radius: 0; 269 | } 270 | 271 | .alert { 272 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); 273 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 274 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 275 | } 276 | 277 | .alert-success { 278 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); 279 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 280 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 281 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 282 | background-repeat: repeat-x; 283 | border-color: #b2dba1; 284 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 285 | } 286 | 287 | .alert-info { 288 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); 289 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 290 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 291 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 292 | background-repeat: repeat-x; 293 | border-color: #9acfea; 294 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 295 | } 296 | 297 | .alert-warning { 298 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); 299 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 300 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 301 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 302 | background-repeat: repeat-x; 303 | border-color: #f5e79e; 304 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 305 | } 306 | 307 | .alert-danger { 308 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); 309 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 310 | background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 311 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 312 | background-repeat: repeat-x; 313 | border-color: #dca7a7; 314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 315 | } 316 | 317 | .progress { 318 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); 319 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 320 | background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 321 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 322 | background-repeat: repeat-x; 323 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 324 | } 325 | 326 | .progress-bar { 327 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 328 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); 329 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 330 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 331 | background-repeat: repeat-x; 332 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 333 | } 334 | 335 | .progress-bar-success { 336 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 337 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); 338 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 339 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 340 | background-repeat: repeat-x; 341 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 342 | } 343 | 344 | .progress-bar-info { 345 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 346 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 347 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 348 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 349 | background-repeat: repeat-x; 350 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 351 | } 352 | 353 | .progress-bar-warning { 354 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 355 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 356 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 357 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 358 | background-repeat: repeat-x; 359 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 360 | } 361 | 362 | .progress-bar-danger { 363 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 364 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); 365 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 366 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 367 | background-repeat: repeat-x; 368 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 369 | } 370 | 371 | .list-group { 372 | border-radius: 4px; 373 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 374 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 375 | } 376 | 377 | .list-group-item.active, 378 | .list-group-item.active:hover, 379 | .list-group-item.active:focus { 380 | text-shadow: 0 -1px 0 #3071a9; 381 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); 382 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); 383 | background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); 384 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 385 | background-repeat: repeat-x; 386 | border-color: #3278b3; 387 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 388 | } 389 | 390 | .panel { 391 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 392 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 393 | } 394 | 395 | .panel-default > .panel-heading { 396 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); 397 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 398 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 399 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 400 | background-repeat: repeat-x; 401 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 402 | } 403 | 404 | .panel-primary > .panel-heading { 405 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 406 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); 407 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 408 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 409 | background-repeat: repeat-x; 410 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 411 | } 412 | 413 | .panel-success > .panel-heading { 414 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); 415 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 416 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 417 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 418 | background-repeat: repeat-x; 419 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 420 | } 421 | 422 | .panel-info > .panel-heading { 423 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); 424 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 425 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 426 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 427 | background-repeat: repeat-x; 428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 429 | } 430 | 431 | .panel-warning > .panel-heading { 432 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); 433 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 434 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 435 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 436 | background-repeat: repeat-x; 437 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 438 | } 439 | 440 | .panel-danger > .panel-heading { 441 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); 442 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 443 | background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 444 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 445 | background-repeat: repeat-x; 446 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 447 | } 448 | 449 | .well { 450 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); 451 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 452 | background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 453 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 454 | background-repeat: repeat-x; 455 | border-color: #dcdcdc; 456 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 457 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 458 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 459 | } -------------------------------------------------------------------------------- /server/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.2 by @fat and @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Designed and built with all the love in the world by @mdo and @fat. 7 | */ 8 | 9 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e0e0e0));background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-moz-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe0e0e0',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#2d6ca2));background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:-moz-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);background-repeat:repeat-x;border-color:#2b669a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff2d6ca2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#419641));background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);background-repeat:repeat-x;border-color:#3e8f3e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff419641',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#eb9316));background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);background-repeat:repeat-x;border-color:#e38d13;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffeb9316',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c12e2a));background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);background-repeat:repeat-x;border-color:#b92c28;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc12e2a',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#2aabd2));background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);background-repeat:repeat-x;border-color:#28a4c9;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2aabd2',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar-default{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f3f3f3));background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff3f3f3',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.075);box-shadow:inset 0 3px 9px rgba(0,0,0,0.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-gradient(linear,left 0,left 100%,from(#222),to(#282828));background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-moz-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff282828',GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,0.25);box-shadow:inset 0 3px 9px rgba(0,0,0,0.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /server/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/server/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /server/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/server/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /server/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pebble-hacks/aviator/0d7def941b84365d7d632ca5ce029caa1a6e29af/server/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aviator v2.0 Config 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |

Aviator v2.0

17 | 18 |
19 |

Seconds

20 |

Display seconds units on digital clock.

21 |
22 | 25 | 28 |
29 |
30 |

Invert

31 |

Invert the colour scheme.

32 |
33 | 36 | 39 |
40 |
41 |

Bluetooth Vibe

42 |

Vibrate on Bluetooth disconnect.

43 |
44 | 47 | 50 |
51 |
52 |

Good Vibrations

53 |

Vibrate every n minutes. (0 to disable)

54 |
55 | 58 |
59 |
60 |

Hands

61 |

Show hands on the clock face.

62 |
63 | 66 | 69 |
70 |
71 |

Style

72 |

Choose display style.

73 |
74 | 77 | 80 | 83 |
84 |
85 |

Background

86 |

Change the appearance of the clock face.

87 |
88 | 91 | 94 | 97 | 100 |
101 |
102 |
103 | 104 |
105 |
106 |
107 | 108 | 111 | 112 | 310 | 311 | 312 | -------------------------------------------------------------------------------- /server/index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aviator v2.0 Config 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |

Aviator v2.0

17 | 18 |
19 |

Big Mode

20 |

Bigger fonts for those of us with poor eyesight.

21 |
22 | 25 | 28 |
29 |
30 |

Seconds

31 |

Display seconds units on digital clock. When using 'Big Mode', this toggles blinking cursor.

32 |
33 | 36 | 39 |
40 |
41 |

Invert

42 |

Invert the colour scheme.

43 |
44 | 47 | 50 |
51 |
52 |

Bluetooth Vibe

53 |

Vibrate on Bluetooth disconnect.

54 |
55 | 58 | 61 |
62 |
63 |

Good Vibrations

64 |

Vibrate every n minutes. (0 to disable)

65 |
66 | 69 |
70 |
71 |

Hands

72 |

Show hands on the clock face.

73 |
74 | 77 | 80 |
81 |
82 |

Style

83 |

Choose display style.

84 |
85 | 88 | 91 | 94 |
95 |
96 |

Timezone

97 |

Secondary timezone. Requires: Style='Local/Timezone'

98 |
99 | 192 |
193 |
194 |

Background

195 |

Change the appearance of the clock face.

196 |
197 | 200 | 203 | 206 | 209 |
210 |
211 |
212 | 213 |
214 |
215 |
216 | 217 | 220 | 221 | 452 | 453 | 454 | -------------------------------------------------------------------------------- /server/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.2 by @fat and @mdo 3 | * Copyright 2013 Twitter, Inc. 4 | * Licensed under http://www.apache.org/licenses/LICENSE-2.0 5 | * 6 | * Designed and built with all the love in the world by @mdo and @fat. 7 | */ 8 | 9 | if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); -------------------------------------------------------------------------------- /server/manifest.appcache: -------------------------------------------------------------------------------- 1 | CACHE MANIFEST 2 | # 28-03-2014 - v0.1 3 | index.html 4 | index2.html 5 | 6 | # Javascript 7 | js/bootstrap.min.js 8 | js/jquery.min.js 9 | 10 | # Stylesheets 11 | css/bootstrap.min.css 12 | css/bootstrap-theme.min.css 13 | 14 | # Fonts 15 | fonts/glyphicons-halflings-regular.svg 16 | fonts/glyphicons-halflings-regular.eot 17 | fonts/glyphicons-halflings-regular.ttf 18 | fonts/glyphicons-halflings-regular.woff 19 | -------------------------------------------------------------------------------- /src/blur.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "effects.h" 4 | 5 | #ifdef PBL_COLOR 6 | static void blur_(uint8_t *bitmap_data, int bytes_per_row, GRect position, uint16_t line, uint8_t *dest, uint8_t radius){ 7 | uint8_t (*fb_a)[bytes_per_row] = (uint8_t (*)[bytes_per_row])bitmap_data; 8 | uint16_t total[3] = {0,0,0}; 9 | uint8_t nb_points = 0; 10 | GPoint p = {0,0}; 11 | for (uint16_t x = 0; x < position.size.w; ++x) { 12 | total[0] = total[1] = total[2] = 0; 13 | nb_points = 0; 14 | p.y = position.origin.y + line - radius; 15 | for (uint8_t ky = 0; ky <= 2*radius; ++ky){ 16 | p.x = position.origin.x + x - radius; 17 | for (uint8_t kx = 0; kx <= 2*radius; ++kx){ 18 | if(grect_contains_point(&position, &p)){ 19 | GColor8 color = (GColor8)fb_a[p.y][p.x]; 20 | total[0] += color.r; 21 | total[1] += color.g; 22 | total[2] += color.b; 23 | nb_points++; 24 | } 25 | p.x++; 26 | } 27 | p.y++; 28 | } 29 | total[0] = (total[0] * 0x55) / nb_points; 30 | total[1] = (total[1] * 0x55) / nb_points; 31 | total[2] = (total[2] * 0x55) / nb_points; 32 | dest[x] = GColorFromRGB(total[0], total[1], total[2]).argb; 33 | } 34 | } 35 | #endif 36 | 37 | void effect_blur(GContext* ctx, GRect position, void* param){ 38 | #ifdef PBL_COLOR 39 | //capturing framebuffer bitmap 40 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 41 | uint8_t *bitmap_data = gbitmap_get_data(fb); 42 | int bytes_per_row = gbitmap_get_bytes_per_row(fb); 43 | 44 | 45 | 46 | uint8_t radius = (uint8_t)(uint32_t)param; // Not very elegant... sorry 47 | uint8_t (*fb_a)[bytes_per_row] = (uint8_t (*)[bytes_per_row])bitmap_data; 48 | uint16_t offset_x = position.origin.x; 49 | uint16_t offset_y = position.origin.y; 50 | uint16_t width = position.size.w; 51 | uint16_t height = position.size.h; 52 | 53 | uint8_t *buffer = malloc(width * (radius + 1)); 54 | 55 | uint16_t h=0; 56 | for(; h<(radius+1); h++){ 57 | blur_(bitmap_data, bytes_per_row, position, h, buffer + h*width, radius); 58 | } 59 | 60 | for(; h 2 | #include "effect_layer.h" 3 | #include "effects.h" 4 | 5 | // Find the offset of parent layer pointer 6 | static uint8_t find_parent_offset() { 7 | Layer* p = layer_create(GRect(0,0,32,32)); 8 | Layer* l = layer_create(GRect(0,0,16,16)); 9 | layer_add_child(p,l); 10 | 11 | uint8_t i=0; 12 | while(i<16 && *(((Layer**)(void*)l)+i)!=p) ++i; 13 | 14 | if(*(((Layer**)(void*)l)+i)!=p) { 15 | i=0xff; 16 | APP_LOG(APP_LOG_LEVEL_ERROR,"EffectLayer library was unable to find the parent layer offset! Your app will probably crash (sorry) :("); 17 | } 18 | 19 | layer_destroy(l); 20 | layer_destroy(p); 21 | return i; 22 | } 23 | 24 | // on layer update - apply effect 25 | static void effect_layer_update_proc(Layer *me, GContext* ctx) { 26 | static uint8_t parent_layer_offset = 0xff; 27 | if(parent_layer_offset == 0xff) { 28 | parent_layer_offset = find_parent_offset(); 29 | } 30 | 31 | // retrieving layer and its real coordinates 32 | EffectLayer* effect_layer = (EffectLayer*)(layer_get_data(me)); 33 | GRect layer_frame = layer_get_frame(me); 34 | Layer* l = me; 35 | while((l=((Layer**)(void*)l)[parent_layer_offset])) { 36 | GRect parent_frame = layer_get_frame(l); 37 | layer_frame.origin.x += parent_frame.origin.x; 38 | layer_frame.origin.y += parent_frame.origin.y; 39 | } 40 | 41 | // Applying effects 42 | for(uint8_t i=0; effect_layer->effects[i] && ieffects[i](ctx, layer_frame, effect_layer->params[i]); 43 | } 44 | 45 | // create effect layer 46 | EffectLayer* effect_layer_create(GRect frame) { 47 | 48 | //creating base layer 49 | Layer* layer =layer_create_with_data(frame, sizeof(EffectLayer)); 50 | layer_set_update_proc(layer, effect_layer_update_proc); 51 | EffectLayer* effect_layer = (EffectLayer*)layer_get_data(layer); 52 | memset(effect_layer,0,sizeof(EffectLayer)); 53 | effect_layer->layer = layer; 54 | 55 | return effect_layer; 56 | } 57 | 58 | //destroy effect layer 59 | void effect_layer_destroy(EffectLayer *effect_layer) { 60 | // precaution 61 | if (effect_layer != NULL && effect_layer->layer != NULL) { 62 | layer_destroy(effect_layer->layer); 63 | effect_layer->layer = NULL; 64 | effect_layer = NULL; 65 | } 66 | 67 | } 68 | 69 | // returns base layer 70 | Layer* effect_layer_get_layer(EffectLayer *effect_layer){ 71 | return effect_layer->layer; 72 | } 73 | 74 | //sets frame for effect layer 75 | void effect_layer_set_frame(EffectLayer *effect_layer, GRect frame) { 76 | layer_set_frame(effect_layer->layer, frame); 77 | } 78 | 79 | //adds effect to the layer 80 | void effect_layer_add_effect(EffectLayer *effect_layer, effect_cb* effect, void* param) { 81 | if(effect_layer->next_effect < MAX_EFFECTS) { 82 | effect_layer->effects[effect_layer->next_effect] = effect; 83 | effect_layer->params[effect_layer->next_effect] = param; 84 | ++effect_layer->next_effect; 85 | } 86 | } 87 | 88 | //removes last added effect 89 | void effect_layer_remove_effect(EffectLayer *effect_layer) { 90 | if(effect_layer->next_effect > 0) { 91 | effect_layer->effects[effect_layer->next_effect - 1] = NULL; 92 | effect_layer->params[effect_layer->next_effect - 1] = NULL; 93 | --effect_layer->next_effect; 94 | } 95 | } -------------------------------------------------------------------------------- /src/effect_layer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "effects.h" 4 | 5 | //number of supported effects on a single effect_layer (must be <= 255) 6 | #define MAX_EFFECTS 4 7 | 8 | // structure of effect layer 9 | typedef struct { 10 | Layer* layer; 11 | effect_cb* effects[MAX_EFFECTS]; 12 | void* params[MAX_EFFECTS]; 13 | uint8_t next_effect; 14 | } EffectLayer; 15 | 16 | 17 | //creates effect layer 18 | EffectLayer* effect_layer_create(GRect frame); 19 | 20 | //destroys effect layer 21 | void effect_layer_destroy(EffectLayer *effect_layer); 22 | 23 | //adds effect for the layer 24 | void effect_layer_add_effect(EffectLayer *effect_layer, effect_cb* effect, void* param); 25 | 26 | //removes last added effect 27 | void effect_layer_remove_effect(EffectLayer *effect_layer); 28 | 29 | //gets layer 30 | Layer* effect_layer_get_layer(EffectLayer *effect_layer); 31 | 32 | //sets effect layer frame 33 | void effect_layer_set_frame(EffectLayer *effect_layer, GRect frame); 34 | 35 | // Recreate inverter_layer for BASALT 36 | #ifndef PBL_PLATFORM_APLITE 37 | #define InverterLayer EffectLayer 38 | #define inverter_layer_create(frame)({ EffectLayer* _el=effect_layer_create(frame); effect_layer_add_effect(_el,effect_invert,NULL);_el; }) 39 | #define inverter_layer_get_layer effect_layer_get_layer 40 | #define inverter_layer_destroy effect_layer_destroy 41 | #endif 42 | -------------------------------------------------------------------------------- /src/effects.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "effects.h" 3 | #include "math.h" 4 | 5 | 6 | // { ********* Graphics utility functions (probablu should be seaparated into anothe file?) ********* 7 | 8 | 9 | 10 | // set pixel color at given coordinates 11 | void set_pixel(BitmapInfo bitmap_info, int y, int x, uint8_t color) { 12 | 13 | #ifdef PBL_PLATFORM_BASALT 14 | if (bitmap_info.bitmap_format == GBitmapFormat1BitPalette) { // for 1bit palette bitmap on Basalt --- verify if it needs to be different 15 | bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8] ^= (-color ^ bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8]) & (1 << (x % 8)); 16 | #else 17 | if (bitmap_info.bitmap_format == GBitmapFormat1Bit) { // for 1 bit bitmap on Aplite --- verify if it needs to be different 18 | bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8] ^= (-color ^ bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8]) & (1 << (x % 8)); 19 | #endif 20 | } else { // othersise (assuming GBitmapFormat8Bit) going byte-wise 21 | bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x] = color; 22 | } 23 | 24 | } 25 | 26 | // get pixel color at given coordinates 27 | uint8_t get_pixel(BitmapInfo bitmap_info, int y, int x) { 28 | 29 | #ifdef PBL_PLATFORM_BASALT 30 | if (bitmap_info.bitmap_format == GBitmapFormat1BitPalette) { // for 1bit palette bitmap on Basalt shifting left to get correct bit 31 | return (bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8] << (x % 8)) & 128; 32 | #else 33 | if (bitmap_info.bitmap_format == GBitmapFormat1Bit) { // for 1 bit bitmap on Aplite - shifting right to get bit 34 | return (bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x / 8] >> (x % 8)) & 1; 35 | #endif 36 | } else { // othersise (assuming GBitmapFormat8Bit) going byte-wise 37 | return bitmap_info.bitmap_data[y*bitmap_info.bytes_per_row + x]; 38 | } 39 | 40 | } 41 | 42 | // converts color between 1bit and 8bit palettes (for GBitmapFormat1BitPalette assuming black & white) 43 | uint8_t PalColor(uint8_t in_color, GBitmapFormat in_format, GBitmapFormat out_format) { 44 | 45 | if ((in_format == 0 || in_format == 2) && out_format == 1) { // converting GBitmapFormat1Bit or GBitmapFormat1BitPalette to GBitmapFormat8Bit 46 | return in_color == 0? 192 : 255; 47 | } else if (in_format == 1 && (out_format == 0 || out_format == 2) ) { // converting GBitmapFormat8Bit to GBitmapFormat1Bit or GBitmapFormat1BitPalette 48 | return in_color == 255? 1 : 0; // for now converting white to white, the rest to black 49 | } else { 50 | return in_color; 51 | } 52 | } 53 | 54 | 55 | // THE EXTREMELY FAST LINE ALGORITHM Variation E (Addition Fixed Point PreCalc Small Display) 56 | // Small Display (256x256) resolution. 57 | // based on algorythm by Po-Han Lin at http://www.edepot.com 58 | void set_line(BitmapInfo bitmap_info, int y, int x, int y2, int x2, uint8_t draw_color, uint8_t skip_color, uint8_t *visited) { 59 | bool yLonger = false; int shortLen=y2-y; int longLen=x2-x; 60 | uint8_t temp_pixel; int temp_x, temp_y; 61 | 62 | if (abs(shortLen)>abs(longLen)) { 63 | int swap=shortLen; 64 | shortLen=longLen; longLen=swap; yLonger=true; 65 | } 66 | 67 | int decInc; 68 | if (longLen==0) decInc=0; 69 | else decInc = (shortLen << 8) / longLen; 70 | 71 | if (yLonger) { 72 | if (longLen>0) { 73 | longLen+=y; 74 | for (int j=0x80+(x<<8);y<=longLen;++y) { 75 | temp_y = y; temp_x = j >> 8; 76 | if (temp_y >=0 && temp_y<168 && temp_x >=0 && temp_x < 144) { 77 | temp_pixel = get_pixel(bitmap_info, temp_y, temp_x); 78 | #ifdef PBL_COLOR // for Basalt drawing pixel if it is not of original color or already drawn color 79 | if (temp_pixel != skip_color && temp_pixel != draw_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); 80 | #else 81 | if (get_pixel(bitmap_info, temp_y, temp_x) != 1) { // for Aplite first check if pixel isn't already marked as set in user-defined array 82 | if (temp_pixel != skip_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); // if pixel isn't of original color - set it 83 | draw_color = 1 - draw_color; // revers pixel for "lined" effect 84 | set_pixel(bitmap_info, temp_y, temp_x, 1); //mark pixel as set 85 | } 86 | #endif 87 | } 88 | j+=decInc; 89 | } 90 | return; 91 | } 92 | longLen+=y; 93 | for (int j=0x80+(x<<8);y>=longLen;--y) { 94 | temp_y = y; temp_x = j >> 8; 95 | if (temp_y >=0 && temp_y<168 && temp_x >=0 && temp_x < 144) { 96 | temp_pixel = get_pixel(bitmap_info, temp_y, temp_x); 97 | #ifdef PBL_COLOR // for Basalt drawing pixel if it is not of original color or already drawn color 98 | if (temp_pixel != skip_color && temp_pixel != draw_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); 99 | #else 100 | if (get_pixel(bitmap_info, temp_y, temp_x) != 1) { // for Aplite first check if pixel isn't already marked as set in user-defined array 101 | if (temp_pixel != skip_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); // if pixel isn't of original color - set it 102 | draw_color = 1 - draw_color; // revers pixel for "lined" effect 103 | set_pixel(bitmap_info, temp_y, temp_x, 1); //mark pixel as set 104 | } 105 | #endif 106 | } 107 | j-=decInc; 108 | } 109 | return; 110 | } 111 | 112 | if (longLen>0) { 113 | longLen+=x; 114 | for (int j=0x80+(y<<8);x<=longLen;++x) { 115 | temp_y = j >> 8; temp_x = x; 116 | if (temp_y >=0 && temp_y<168 && temp_x >=0 && temp_x < 144) { 117 | temp_pixel = get_pixel(bitmap_info, temp_y, temp_x); 118 | #ifdef PBL_COLOR // for Basalt drawing pixel if it is not of original color or already drawn color 119 | if (temp_pixel != skip_color && temp_pixel != draw_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); 120 | #else 121 | if (get_pixel(bitmap_info, temp_y, temp_x) != 1) { // for Aplite first check if pixel isn't already marked as set in user-defined array 122 | if (temp_pixel != skip_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); // if pixel isn't of original color - set it 123 | draw_color = 1 - draw_color; // revers pixel for "lined" effect 124 | set_pixel(bitmap_info, temp_y, temp_x, 1); //mark pixel as set 125 | } 126 | #endif 127 | } 128 | j+=decInc; 129 | } 130 | return; 131 | } 132 | longLen+=x; 133 | for (int j=0x80+(y<<8);x>=longLen;--x) { 134 | temp_y = j >> 8; temp_x = x; 135 | if (temp_y >=0 && temp_y<168 && temp_x >=0 && temp_x < 144) { 136 | temp_pixel = get_pixel(bitmap_info, temp_y, temp_x); 137 | #ifdef PBL_COLOR // for Basalt drawing pixel if it is not of original color or already drawn color 138 | if (temp_pixel != skip_color && temp_pixel != draw_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); 139 | #else 140 | if (get_pixel(bitmap_info, temp_y, temp_x) != 1) { // for Aplite first check if pixel isn't already marked as set in user-defined array 141 | if (temp_pixel != skip_color) set_pixel(bitmap_info, temp_y, temp_x, draw_color); // if pixel isn't of original color - set it 142 | draw_color = 1 - draw_color; // revers pixel for "lined" effect 143 | set_pixel(bitmap_info, temp_y, temp_x, 1); //mark pixel as set 144 | } 145 | #endif 146 | } 147 | j-=decInc; 148 | } 149 | 150 | } 151 | 152 | // ********* Graphics utility functions (probablu should be seaparated into anothe file?) ********* } 153 | 154 | 155 | 156 | // inverter effect. 157 | void effect_invert(GContext* ctx, GRect position, void* param) { 158 | //capturing framebuffer bitmap 159 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 160 | 161 | BitmapInfo bitmap_info; 162 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 163 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 164 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 165 | 166 | for (int y = 0; y < position.size.h; y++) 167 | for (int x = 0; x < position.size.w; x++) 168 | #ifdef PBL_COLOR // on Basalt simple doing NOT on entire returned byte/pixel 169 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, (~get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x))|11000000); 170 | #else // on Aplite since only 1 and 0 is returning, doing "not" by 1 - pixel 171 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, 1 - get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x)); 172 | #endif 173 | 174 | graphics_release_frame_buffer(ctx, fb); 175 | 176 | } 177 | 178 | // colorize effect - given a target color, replace it with a new color 179 | // Added by Martin Norland (@cynorg) 180 | // Parameter: GColor firstColor, GColor secondColor 181 | void effect_colorize(GContext* ctx, GRect position, void* param) { 182 | #ifdef PBL_COLOR // only logical to do anything on Basalt - otherwise you're just ... drawing a black|white GRect 183 | //capturing framebuffer bitmap 184 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 185 | 186 | BitmapInfo bitmap_info; 187 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 188 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 189 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 190 | 191 | EffectColorpair *paint = (EffectColorpair *)param; 192 | 193 | for (int y = 0; y < position.size.h; y++){ 194 | for (int x = 0; x < position.size.w; x++){ 195 | if (gcolor_equal((GColor)get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x), paint->firstColor)){ 196 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, (uint8_t)paint->secondColor.argb); 197 | } 198 | } 199 | graphics_release_frame_buffer(ctx, fb); 200 | } 201 | #endif 202 | } 203 | 204 | 205 | // colorswap effect - swaps two colors in a given area 206 | // Added by Martin Norland (@cynorg) 207 | // Parameter: GColor firstColor, GColor secondColor 208 | void effect_colorswap(GContext* ctx, GRect position, void* param) { 209 | #ifdef PBL_COLOR // only logical to do anything on Basalt - otherwise you're just ... doing an invert 210 | //capturing framebuffer bitmap 211 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 212 | 213 | BitmapInfo bitmap_info; 214 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 215 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 216 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 217 | 218 | EffectColorpair *swap = (EffectColorpair *)param; 219 | GColor pixel; 220 | 221 | for (int y = 0; y < position.size.h; y++){ 222 | for (int x = 0; x < position.size.w; x++){ 223 | pixel.argb = get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 224 | if (gcolor_equal(pixel, swap->firstColor)) 225 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, swap->secondColor.argb); 226 | else if (gcolor_equal(pixel, swap->secondColor)) 227 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, swap->firstColor.argb); 228 | } 229 | graphics_release_frame_buffer(ctx, fb); 230 | } 231 | #endif 232 | } 233 | 234 | // invert black and white only (leaves all other colors intact). 235 | void effect_invert_bw_only(GContext* ctx, GRect position, void* param) { 236 | //capturing framebuffer bitmap 237 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 238 | 239 | BitmapInfo bitmap_info; 240 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 241 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 242 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 243 | 244 | #ifdef PBL_COLOR 245 | GColor pixel; 246 | #endif 247 | 248 | for (int y = 0; y < position.size.h; y++) { 249 | for (int x = 0; x < position.size.w; x++) { 250 | #ifdef PBL_COLOR // on Basalt invert only black or white 251 | pixel.argb = get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 252 | if (gcolor_equal(pixel, GColorBlack)) 253 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, GColorWhite.argb); 254 | else if (gcolor_equal(pixel, GColorWhite)) 255 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, GColorBlack.argb); 256 | #else // on Aplite since only 1 and 0 is returning, doing "not" by 1 - pixel 257 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, 1 - get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x)); 258 | #endif 259 | } 260 | } 261 | 262 | graphics_release_frame_buffer(ctx, fb); 263 | 264 | } 265 | 266 | // invert brightness of colors (leaves hue more or less intact and does not apply to black and white). 267 | void effect_invert_brightness(GContext* ctx, GRect position, void* param) { 268 | #ifdef PBL_COLOR 269 | //capturing framebuffer bitmap 270 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 271 | 272 | BitmapInfo bitmap_info; 273 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 274 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 275 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 276 | 277 | GColor pixel; 278 | GColor pixel_new; 279 | 280 | for (int y = 0; y < position.size.h; y++) { 281 | for (int x = 0; x < position.size.w; x++) { 282 | pixel.argb = get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 283 | 284 | if (!gcolor_equal(pixel, GColorBlack) && !gcolor_equal(pixel, GColorWhite)) { 285 | // Only apply if not black/white (add effect_invert_bw_only for that too) 286 | 287 | // Color spread is not even, so need to handcraft the opposing brightness of colors, 288 | // which is probably subjective and open for improvement 289 | if (gcolor_equal(pixel, GColorOxfordBlue)) 290 | pixel_new = GColorCeleste; 291 | else if (gcolor_equal(pixel, GColorDukeBlue)) 292 | pixel_new = GColorVividCerulean; 293 | else if (gcolor_equal(pixel, GColorBlue)) 294 | pixel_new = GColorPictonBlue; 295 | else if (gcolor_equal(pixel, GColorDarkGreen)) 296 | pixel_new = GColorMintGreen; 297 | else if (gcolor_equal(pixel, GColorMidnightGreen)) 298 | pixel_new = GColorMediumSpringGreen; 299 | else if (gcolor_equal(pixel, GColorCobaltBlue)) 300 | pixel_new = GColorCyan; 301 | else if (gcolor_equal(pixel, GColorBlueMoon)) 302 | pixel_new = GColorElectricBlue; 303 | else if (gcolor_equal(pixel, GColorIslamicGreen)) 304 | pixel_new = GColorMalachite; 305 | else if (gcolor_equal(pixel, GColorJaegerGreen)) 306 | pixel_new = GColorScreaminGreen; 307 | else if (gcolor_equal(pixel, GColorTiffanyBlue)) 308 | pixel_new = GColorCadetBlue; 309 | else if (gcolor_equal(pixel, GColorVividCerulean)) 310 | pixel_new = GColorDukeBlue; 311 | else if (gcolor_equal(pixel, GColorGreen)) 312 | pixel_new = GColorMayGreen; 313 | else if (gcolor_equal(pixel, GColorMalachite)) 314 | pixel_new = GColorIslamicGreen; 315 | else if (gcolor_equal(pixel, GColorMediumSpringGreen)) 316 | pixel_new = GColorMidnightGreen; 317 | else if (gcolor_equal(pixel, GColorCyan)) 318 | pixel_new = GColorCobaltBlue; 319 | else if (gcolor_equal(pixel, GColorBulgarianRose)) 320 | pixel_new = GColorMelon; 321 | else if (gcolor_equal(pixel, GColorImperialPurple)) 322 | pixel_new = GColorRichBrilliantLavender; 323 | else if (gcolor_equal(pixel, GColorIndigo)) 324 | pixel_new = GColorLavenderIndigo; 325 | else if (gcolor_equal(pixel, GColorElectricUltramarine)) 326 | pixel_new = GColorVeryLightBlue; 327 | else if (gcolor_equal(pixel, GColorArmyGreen)) 328 | pixel_new = GColorBrass; 329 | else if (gcolor_equal(pixel, GColorDarkGray)) 330 | pixel_new = GColorLightGray; 331 | else if (gcolor_equal(pixel, GColorLiberty)) 332 | pixel_new = GColorBabyBlueEyes; 333 | else if (gcolor_equal(pixel, GColorVeryLightBlue)) 334 | pixel_new = GColorElectricUltramarine; 335 | else if (gcolor_equal(pixel, GColorKellyGreen)) 336 | pixel_new = GColorGreen; 337 | else if (gcolor_equal(pixel, GColorMayGreen)) 338 | pixel_new = GColorMediumAquamarine; 339 | else if (gcolor_equal(pixel, GColorCadetBlue)) 340 | pixel_new = GColorTiffanyBlue; 341 | else if (gcolor_equal(pixel, GColorPictonBlue)) 342 | pixel_new = GColorBlue; 343 | else if (gcolor_equal(pixel, GColorBrightGreen)) 344 | pixel_new = GColorIslamicGreen; 345 | else if (gcolor_equal(pixel, GColorScreaminGreen)) 346 | pixel_new = GColorKellyGreen; 347 | else if (gcolor_equal(pixel, GColorMediumAquamarine)) 348 | pixel_new = GColorMayGreen; 349 | else if (gcolor_equal(pixel, GColorElectricBlue)) 350 | pixel_new = GColorBlueMoon; 351 | else if (gcolor_equal(pixel, GColorDarkCandyAppleRed)) 352 | pixel_new = GColorMelon; 353 | else if (gcolor_equal(pixel, GColorJazzberryJam)) 354 | pixel_new = GColorBrilliantRose; 355 | else if (gcolor_equal(pixel, GColorPurple)) 356 | pixel_new = GColorShockingPink; 357 | else if (gcolor_equal(pixel, GColorVividViolet)) 358 | pixel_new = GColorPurpureus; 359 | else if (gcolor_equal(pixel, GColorWindsorTan)) 360 | pixel_new = GColorRoseVale; 361 | else if (gcolor_equal(pixel, GColorRoseVale)) 362 | pixel_new = GColorWindsorTan; 363 | else if (gcolor_equal(pixel, GColorPurpureus)) 364 | pixel_new = GColorVividViolet; 365 | else if (gcolor_equal(pixel, GColorLavenderIndigo)) 366 | pixel_new = GColorIndigo; 367 | else if (gcolor_equal(pixel, GColorLimerick)) 368 | pixel_new = GColorPastelYellow; 369 | else if (gcolor_equal(pixel, GColorBrass)) 370 | pixel_new = GColorArmyGreen; 371 | else if (gcolor_equal(pixel, GColorLightGray)) 372 | pixel_new = GColorDarkGray; 373 | else if (gcolor_equal(pixel, GColorBabyBlueEyes)) 374 | pixel_new = GColorLiberty; 375 | else if (gcolor_equal(pixel, GColorSpringBud)) 376 | pixel_new = GColorDarkGreen; 377 | else if (gcolor_equal(pixel, GColorInchworm)) 378 | pixel_new = GColorMidnightGreen; 379 | else if (gcolor_equal(pixel, GColorMintGreen)) 380 | pixel_new = GColorDarkGreen; 381 | else if (gcolor_equal(pixel, GColorCeleste)) 382 | pixel_new = GColorOxfordBlue; 383 | else if (gcolor_equal(pixel, GColorRed)) 384 | pixel_new = GColorSunsetOrange; 385 | else if (gcolor_equal(pixel, GColorFolly)) 386 | pixel_new = GColorMelon; 387 | else if (gcolor_equal(pixel, GColorFashionMagenta)) 388 | pixel_new = GColorMagenta ; 389 | else if (gcolor_equal(pixel, GColorMagenta)) 390 | pixel_new = GColorFashionMagenta; 391 | else if (gcolor_equal(pixel, GColorOrange)) 392 | pixel_new = GColorRajah; 393 | else if (gcolor_equal(pixel, GColorSunsetOrange)) 394 | pixel_new = GColorRed; 395 | else if (gcolor_equal(pixel, GColorBrilliantRose)) 396 | pixel_new = GColorJazzberryJam; 397 | else if (gcolor_equal(pixel, GColorShockingPink)) 398 | pixel_new = GColorPurple; 399 | else if (gcolor_equal(pixel, GColorChromeYellow)) 400 | pixel_new = GColorWindsorTan; 401 | else if (gcolor_equal(pixel, GColorRajah)) 402 | pixel_new = GColorOrange; 403 | else if (gcolor_equal(pixel, GColorMelon)) 404 | pixel_new = GColorDarkCandyAppleRed; 405 | else if (gcolor_equal(pixel, GColorRichBrilliantLavender)) 406 | pixel_new = GColorImperialPurple; 407 | else if (gcolor_equal(pixel, GColorYellow)) 408 | pixel_new = GColorChromeYellow; 409 | else if (gcolor_equal(pixel, GColorIcterine)) 410 | pixel_new = GColorChromeYellow; 411 | else if (gcolor_equal(pixel, GColorPastelYellow)) 412 | pixel_new = GColorChromeYellow; 413 | 414 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, pixel_new.argb); 415 | } 416 | } 417 | } 418 | 419 | graphics_release_frame_buffer(ctx, fb); 420 | 421 | #endif 422 | } 423 | 424 | // vertical mirror effect. 425 | void effect_mirror_vertical(GContext* ctx, GRect position, void* param) { 426 | uint8_t temp_pixel; 427 | 428 | //capturing framebuffer bitmap 429 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 430 | 431 | BitmapInfo bitmap_info; 432 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 433 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 434 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 435 | 436 | for (int y = 0; y < position.size.h / 2 ; y++) 437 | for (int x = 0; x < position.size.w; x++){ 438 | temp_pixel = get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 439 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, get_pixel(bitmap_info, position.origin.y + position.size.h - y - 2, x + position.origin.x)); 440 | set_pixel(bitmap_info, position.origin.y + position.size.h - y - 2, x + position.origin.x, temp_pixel); 441 | } 442 | 443 | graphics_release_frame_buffer(ctx, fb); 444 | } 445 | 446 | 447 | // horizontal mirror effect. 448 | void effect_mirror_horizontal(GContext* ctx, GRect position, void* param) { 449 | uint8_t temp_pixel; 450 | 451 | //capturing framebuffer bitmap 452 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 453 | 454 | BitmapInfo bitmap_info; 455 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 456 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 457 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 458 | 459 | for (int y = 0; y < position.size.h; y++) 460 | for (int x = 0; x < position.size.w / 2; x++){ 461 | temp_pixel = get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 462 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, get_pixel(bitmap_info, y + position.origin.y, position.origin.x + position.size.w - x - 2)); 463 | set_pixel(bitmap_info, y + position.origin.y, position.origin.x + position.size.w - x - 2, temp_pixel); 464 | } 465 | 466 | graphics_release_frame_buffer(ctx, fb); 467 | } 468 | 469 | // Rotate 90 degrees 470 | // Added by Ron64 471 | // Parameter: true: rotate right/clockwise, false: rotate left/counter_clockwise 472 | void effect_rotate_90_degrees(GContext* ctx, GRect position, void* param){ 473 | 474 | //capturing framebuffer bitmap 475 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 476 | 477 | BitmapInfo bitmap_info; 478 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 479 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 480 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 481 | 482 | bool right = (bool)param; 483 | uint8_t qtr, xCn, yCn, temp_pixel; 484 | xCn= position.origin.x + position.size.w /2; 485 | yCn= position.origin.y + position.size.h /2; 486 | qtr=position.size.w; 487 | if (position.size.h < qtr) 488 | qtr= position.size.h; 489 | qtr= qtr/2; 490 | 491 | for (int c1 = 0; c1 < qtr; c1++) 492 | for (int c2 = 1; c2 < qtr; c2++){ 493 | temp_pixel = get_pixel(bitmap_info, yCn +c1, xCn +c2); 494 | if (right){ 495 | set_pixel(bitmap_info, yCn +c1, xCn +c2, get_pixel(bitmap_info, yCn -c2, xCn +c1)); 496 | set_pixel(bitmap_info, yCn -c2, xCn +c1, get_pixel(bitmap_info, yCn -c1, xCn -c2)); 497 | set_pixel(bitmap_info, yCn -c1, xCn -c2, get_pixel(bitmap_info, yCn +c2, xCn -c1)); 498 | set_pixel(bitmap_info, yCn +c2, xCn -c1, temp_pixel); 499 | } 500 | else{ 501 | set_pixel(bitmap_info, yCn +c1, xCn +c2, get_pixel(bitmap_info, yCn +c2, xCn -c1)); 502 | set_pixel(bitmap_info, yCn +c2, xCn -c1, get_pixel(bitmap_info, yCn -c1, xCn -c2)); 503 | set_pixel(bitmap_info, yCn -c1, xCn -c2, get_pixel(bitmap_info, yCn -c2, xCn +c1)); 504 | set_pixel(bitmap_info, yCn -c2, xCn +c1, temp_pixel); 505 | } 506 | } 507 | 508 | graphics_release_frame_buffer(ctx, fb); 509 | } 510 | 511 | // Zoom effect. 512 | // Added by Ron64 513 | // Parameter: Y zoom (high byte) X zoom(low byte), 0x10 no zoom 0x20 200% 0x08 50%, 514 | // use the percentage macro EL_ZOOM(150,60). In this example: Y- zoom in 150%, X- zoom out to 60% 515 | void effect_zoom(GContext* ctx, GRect position, void* param){ 516 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 517 | 518 | BitmapInfo bitmap_info; 519 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 520 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 521 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 522 | 523 | uint8_t xCn, yCn, Y1,X1, ratioY, ratioX; 524 | xCn= position.origin.x + position.size.w /2; 525 | yCn= position.origin.y + position.size.h /2; 526 | 527 | ratioY= (int32_t)param >>8 & 0xFF; 528 | ratioX= (int32_t)param & 0xFF; 529 | 530 | for (int y = 0; y <= position.size.h>>1; y++) 531 | for (int x = 0; x <= position.size.w>>1; x++) 532 | { 533 | //yS,xS scan source: centre to out or out to centre 534 | int8_t yS = (ratioY>16) ? (position.size.h/2)- y: y; 535 | int8_t xS = (ratioX>16) ? (position.size.w/2)- x: x; 536 | Y1= (yS<<4) /ratioY; 537 | X1= (xS<<4) /ratioX; 538 | set_pixel(bitmap_info, yCn +yS, xCn +xS, get_pixel(bitmap_info, yCn +Y1, xCn +X1)); 539 | set_pixel(bitmap_info, yCn +yS, xCn -xS, get_pixel(bitmap_info, yCn +Y1, xCn -X1)); 540 | set_pixel(bitmap_info, yCn -yS, xCn +xS, get_pixel(bitmap_info, yCn -Y1, xCn +X1)); 541 | set_pixel(bitmap_info, yCn -yS, xCn -xS, get_pixel(bitmap_info, yCn -Y1, xCn -X1)); 542 | } 543 | graphics_release_frame_buffer(ctx, fb); 544 | //Todo: Should probably reduce Y size on zoom out or limit reading beyond edge of screen. 545 | } 546 | 547 | // Lens effect. 548 | // Added by Ron64 549 | // Parameters: lens focal(high byte) and object distance(low byte) 550 | void effect_lens(GContext* ctx, GRect position, void* param){ 551 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 552 | 553 | BitmapInfo bitmap_info; 554 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 555 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 556 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 557 | 558 | uint8_t d,r, xCn, yCn; 559 | 560 | xCn= position.origin.x + position.size.w /2; 561 | yCn= position.origin.y + position.size.h /2; 562 | d=position.size.w; 563 | if (position.size.h < d) 564 | d= position.size.h; 565 | r= d/2; // radius of lens 566 | float focal = (int32_t)param >>8 & 0xFF;// focal point of lens 567 | float obj_dis = (int32_t)param & 0xFF;//distance of object from focal point. 568 | 569 | for (int y = r; y >= 0; --y) 570 | for (int x = r; x >= 0; --x) 571 | if (x*x+y*y < r*r) 572 | { 573 | int Y1= my_tan(my_asin(y/focal))*obj_dis; 574 | int X1= my_tan(my_asin(x/focal))*obj_dis; 575 | set_pixel(bitmap_info, yCn +y, xCn +x, get_pixel(bitmap_info, yCn +Y1, xCn +X1)); 576 | set_pixel(bitmap_info, yCn +y, xCn -x, get_pixel(bitmap_info, yCn +Y1, xCn -X1)); 577 | set_pixel(bitmap_info, yCn -y, xCn +x, get_pixel(bitmap_info, yCn -Y1, xCn +X1)); 578 | set_pixel(bitmap_info, yCn -y, xCn -x, get_pixel(bitmap_info, yCn -Y1, xCn -X1)); 579 | } 580 | graphics_release_frame_buffer(ctx, fb); 581 | //Todo: Change to lock-up arcsin table in the future. (Currently using floating point math library that is relatively big & slow) 582 | } 583 | 584 | // mask effect. 585 | // see struct EffectMask for parameter description 586 | void effect_mask(GContext* ctx, GRect position, void* param) { 587 | GColor temp_pixel; 588 | EffectMask *mask = (EffectMask *)param; 589 | 590 | //drawing background - only if real color is passed 591 | if (!gcolor_equal(mask->background_color, GColorClear)) { 592 | graphics_context_set_fill_color(ctx, mask->background_color); 593 | graphics_fill_rect(ctx, GRect(0, 0, position.size.w, position.size.h), 0, GCornerNone); 594 | } 595 | 596 | //if text mask is used - drawing text 597 | if (mask->text) { 598 | graphics_context_set_text_color(ctx, mask->mask_color); 599 | graphics_draw_text(ctx, mask->text, mask->font, GRect(0, 0, position.size.w, position.size.h), mask->text_overflow, mask->text_align, NULL); 600 | } else if (mask->bitmap_mask) { // othersise - bitmap mask is used - draw bimap 601 | graphics_draw_bitmap_in_rect(ctx, mask->bitmap_mask, GRect(0, 0, position.size.w, position.size.h)); 602 | } 603 | 604 | //capturing framebuffer bitmap 605 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 606 | 607 | BitmapInfo bitmap_info; 608 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 609 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 610 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 611 | 612 | //capturing background bitmap 613 | BitmapInfo bg_bitmap_info; 614 | bg_bitmap_info.bitmap_data = gbitmap_get_data(mask->bitmap_background); 615 | bg_bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(mask->bitmap_background); 616 | bg_bitmap_info.bitmap_format = gbitmap_get_format(mask->bitmap_background); 617 | 618 | //looping throughout layer replacing mask with bg bitmap 619 | for (int y = 0; y < position.size.h; y++) 620 | for (int x = 0; x < position.size.w; x++) { 621 | temp_pixel = (GColor)get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 622 | if (gcolor_equal(temp_pixel, mask->mask_color)) { 623 | // getting pixel from background bitmap (adjusted to pallette by PalColor function because palette of bg bitmap and framebuffer may differ) 624 | // *** APP_LOG(APP_LOG_LEVEL_DEBUG, "get_pixel = %d, pal_color = %d", get_pixel(bg_bitmap_info, y + position.origin.y, x + position.origin.x), PalColor(get_pixel(bg_bitmap_info, y + position.origin.y, x + position.origin.x), bg_bitmap_info.bitmap_format, bitmap_info.bitmap_format)); 625 | set_pixel(bitmap_info, y + position.origin.y, x + position.origin.x, PalColor(get_pixel(bg_bitmap_info, y + position.origin.y, x + position.origin.x), bg_bitmap_info.bitmap_format, bitmap_info.bitmap_format)); 626 | } 627 | } 628 | 629 | graphics_release_frame_buffer(ctx, fb); 630 | 631 | } 632 | 633 | void effect_fps(GContext* ctx, GRect position, void* param) { 634 | static GFont font = NULL; 635 | static char buff[16]; 636 | time_t tt; 637 | uint16_t ms; 638 | 639 | if(((EffectFPS*)param)->starttt) { 640 | time_ms(&tt,&ms); 641 | ++((EffectFPS*)param)->frame; 642 | uint32_t fp100s = (100000*((EffectFPS*)param)->frame)/((tt-((EffectFPS*)param)->starttt)*1000+ms-((EffectFPS*)param)->startms); 643 | snprintf(buff,sizeof(buff),"FPS:%d.%02d",(int)fp100s/100,(int)fp100s%100); 644 | graphics_context_set_stroke_color(ctx, GColorWhite); 645 | graphics_draw_text(ctx, buff, font, GRect(0, 0, position.size.w, position.size.h), GTextOverflowModeWordWrap, GTextAlignmentLeft, NULL); 646 | } 647 | else { 648 | // First call 649 | if(!font) font = fonts_get_system_font(FONT_KEY_GOTHIC_14); 650 | time_ms(&((EffectFPS*)param)->starttt,&((EffectFPS*)param)->startms); 651 | ((EffectFPS*)param)->frame = 0; 652 | } 653 | } 654 | 655 | 656 | // shadow effect. 657 | // see struct EffecOffset for parameter description 658 | void effect_shadow(GContext* ctx, GRect position, void* param) { 659 | GColor temp_pixel; 660 | int shadow_x, shadow_y; 661 | EffectOffset *shadow = (EffectOffset *)param; 662 | 663 | #ifndef PBL_COLOR 664 | uint8_t draw_color = gcolor_equal(shadow->offset_color, GColorWhite)? 1 : 0; 665 | uint8_t skip_color = gcolor_equal(shadow->orig_color, GColorWhite)? 1 : 0; 666 | #endif 667 | 668 | //capturing framebuffer bitmap 669 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 670 | 671 | BitmapInfo bitmap_info; 672 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 673 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 674 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 675 | 676 | 677 | //looping throughout making shadow 678 | for (int y = 0; y < position.size.h; y++) 679 | for (int x = 0; x < position.size.w; x++) { 680 | temp_pixel = (GColor)get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 681 | 682 | if (gcolor_equal(temp_pixel, shadow->orig_color)) { 683 | shadow_x = x + position.origin.x + shadow->offset_x; 684 | shadow_y = y + position.origin.y + shadow->offset_y; 685 | 686 | if (shadow->option == 1) { 687 | #ifdef PBL_COLOR // for Basalt simple calling line-drawing routine 688 | set_line(bitmap_info, y + position.origin.y, x + position.origin.x, shadow_y, shadow_x, shadow->offset_color.argb, shadow->orig_color.argb, NULL); 689 | #else // for Aplite - passing user-defined array to determine if pixels have been set or not 690 | set_line(bitmap_info, y + position.origin.y, x + position.origin.x, shadow_y, shadow_x, draw_color, skip_color, shadow->aplite_visited); 691 | #endif 692 | 693 | } else { 694 | 695 | if (shadow_x >= 0 && shadow_x <=143 && shadow_y >= 0 && shadow_y <= 167) { 696 | 697 | temp_pixel = (GColor)get_pixel(bitmap_info, shadow_y, shadow_x); 698 | if (!gcolor_equal(temp_pixel, shadow->orig_color) & !gcolor_equal(temp_pixel, shadow->offset_color) ) { 699 | #ifdef PBL_COLOR 700 | set_pixel(bitmap_info, shadow_y, shadow_x, shadow->offset_color.argb); 701 | #else 702 | set_pixel(bitmap_info, shadow_y, shadow_x, gcolor_equal(shadow->offset_color, GColorWhite)? 1 : 0); 703 | #endif 704 | } 705 | } 706 | 707 | } 708 | 709 | 710 | } 711 | } 712 | 713 | graphics_release_frame_buffer(ctx, fb); 714 | 715 | } 716 | 717 | void effect_outline(GContext* ctx, GRect position, void* param) { 718 | GColor temp_pixel; 719 | int outlinex[4]; 720 | int outliney[4]; 721 | EffectOffset *outline = (EffectOffset *)param; 722 | 723 | //capturing framebuffer bitmap 724 | GBitmap *fb = graphics_capture_frame_buffer(ctx); 725 | 726 | BitmapInfo bitmap_info; 727 | bitmap_info.bitmap_data = gbitmap_get_data(fb); 728 | bitmap_info.bytes_per_row = gbitmap_get_bytes_per_row(fb); 729 | bitmap_info.bitmap_format = gbitmap_get_format(fb); 730 | 731 | 732 | //loop through pixels from framebuffer 733 | for (int y = 0; y < position.size.h; y++) 734 | for (int x = 0; x < position.size.w; x++) { 735 | temp_pixel = (GColor)get_pixel(bitmap_info, y + position.origin.y, x + position.origin.x); 736 | 737 | if (gcolor_equal(temp_pixel, outline->orig_color)) { 738 | // TODO: there's probably a more efficient way to do this 739 | outlinex[0] = x + position.origin.x - outline->offset_x; 740 | outliney[0] = y + position.origin.y - outline->offset_y; 741 | outlinex[1] = x + position.origin.x + outline->offset_x; 742 | outliney[1] = y + position.origin.y + outline->offset_y; 743 | outlinex[2] = x + position.origin.x - outline->offset_x; 744 | outliney[2] = y + position.origin.y + outline->offset_y; 745 | outlinex[3] = x + position.origin.x + outline->offset_x; 746 | outliney[3] = y + position.origin.y - outline->offset_y; 747 | 748 | 749 | for (int i = 0; i < 4; i++) { 750 | // TODO: centralize the constants 751 | if (outlinex[i] >= 0 && outlinex[i] <=144 && outliney[i] >= 0 && outliney[i] <= 168) { 752 | temp_pixel = (GColor)get_pixel(bitmap_info, outliney[i], outlinex[i]); 753 | if (!gcolor_equal(temp_pixel, outline->orig_color)) { 754 | #ifdef PBL_COLOR 755 | set_pixel(bitmap_info, outliney[i], outlinex[i], outline->offset_color.argb); 756 | #else 757 | set_pixel(bitmap_info, outliney[i], outlinex[i], gcolor_equal(outline->offset_color, GColorWhite)? 1 : 0); 758 | #endif 759 | } 760 | } 761 | } 762 | } 763 | } 764 | 765 | graphics_release_frame_buffer(ctx, fb); 766 | } 767 | -------------------------------------------------------------------------------- /src/effects.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // used to pass bimap info to get/set pixel accurately 5 | typedef struct { 6 | uint8_t *bitmap_data; 7 | int bytes_per_row; 8 | GBitmapFormat bitmap_format; 9 | } BitmapInfo; 10 | 11 | // structure of mask for masking effects 12 | typedef struct { 13 | GBitmap* bitmap_mask; // bitmap used for mask (when masking by bitmap) 14 | GBitmap* bitmap_background; // bitmap to show thru mask 15 | GColor mask_color; //color of the mask 16 | GColor background_color; // color of the background 17 | char* text; // text used for mask (when when masking by text) 18 | GFont font; // font used for text mask; 19 | GTextOverflowMode text_overflow; // overflow used for text mask; 20 | GTextAlignment text_align; // alignment used for text masks 21 | } EffectMask; 22 | 23 | // structure for FPS effect 24 | typedef struct { 25 | time_t starttt; // time_t at the first refresh 26 | uint16_t startms; // ms at the first refresh 27 | uint32_t frame; // frame number 28 | } EffectFPS; 29 | 30 | // structure for effect at given offset (currently used for effect_shadow) 31 | typedef struct { 32 | GColor orig_color; //color of pixel being ofset 33 | GColor offset_color; //new color of pixel at offset coords 34 | int8_t offset_x; // horizontal ofset 35 | int8_t offset_y; // vertical offset 36 | int8_t option; // optional parameter (currently in effect_shadow 1=draw long shadow) 37 | uint8_t *aplite_visited; // for Applite holds array of visited pixels 38 | } EffectOffset; 39 | 40 | // structure for color swap effect 41 | typedef struct { 42 | GColor firstColor; // first color (target for colorize, one of set in colorswap) 43 | GColor secondColor; // second color (new color for colorize, other of set in colorswap) 44 | } EffectColorpair; 45 | 46 | typedef void effect_cb(GContext* ctx, GRect position, void* param); 47 | 48 | // inverter effect. 49 | // Added by Yuriy Galanter 50 | effect_cb effect_invert; 51 | 52 | // colorize effect. 53 | // Added by Martin Norland (@cynorg) 54 | effect_cb effect_colorize; 55 | 56 | // colorswap effect. 57 | // Added by Martin Norland (@cynorg) 58 | effect_cb effect_colorswap; 59 | 60 | // Invert only black and white 61 | effect_cb effect_invert_bw_only; 62 | 63 | // Invert brightness of colors (retains hue, does not apply to black and white) 64 | effect_cb effect_invert_brightness; 65 | 66 | // vertical mirror effect. 67 | // Added by Yuriy Galanter 68 | effect_cb effect_mirror_vertical; 69 | 70 | 71 | // horizontal mirror effect. 72 | // Added by Yuriy Galanter 73 | effect_cb effect_mirror_horizontal; 74 | 75 | // Rotate 90 degrees 76 | // Added by Ron64 77 | // Parameter: true: rotate right/clockwise false: rotate left/counter_clockwise 78 | effect_cb effect_rotate_90_degrees; 79 | 80 | // blur effect. 81 | // Added by Grégoire Sage 82 | // Parameter: blur radius 83 | effect_cb effect_blur; 84 | 85 | // Zoom effect 86 | // Added by Ron64 87 | // Parameter: Y zoom (high byte) X zoom(low byte), 0x10 no zoom 0x20 200% 0x08 50%, 88 | // use the percentage macro EL_ZOOM(150,60). In this example: Y- zomm in 150%, X- zoom out to 60% 89 | effect_cb effect_zoom; 90 | 91 | #define EL_ZOOM(x,y) ((void*)((((y)*16/100)|(((x)*16/100)<<8)))) 92 | 93 | // Lens effect 94 | // Added by Ron64 95 | // Parameters: lens focal(high byte) and object distance(low byte) 96 | effect_cb effect_lens; 97 | 98 | #define EL_LENS(f,d) ((void*) ( d|(f<<8))) 99 | 100 | 101 | // mask effect. 102 | // Added by Yuriy Galanter 103 | // see struct EffectMask for parameter description 104 | effect_cb effect_mask; 105 | 106 | // Just displays the average FPS of the app 107 | // Probably works better on a fullscreen effect layer so it can catch all redraw messages 108 | effect_cb effect_fps; 109 | 110 | // shadow effect 111 | // Added by Yuriy Galanter 112 | // uses EffecOffset as a parameter; 113 | effect_cb effect_shadow; 114 | 115 | effect_cb effect_outline; 116 | -------------------------------------------------------------------------------- /src/js/pebble-js-app.js: -------------------------------------------------------------------------------- 1 | var mConfig = {}; 2 | 3 | Pebble.addEventListener("ready", function(e) { 4 | loadLocalData(); 5 | returnConfigToPebble(); 6 | }); 7 | 8 | Pebble.addEventListener("showConfiguration", function(e) { 9 | Pebble.openURL(mConfig.configureUrl); 10 | }); 11 | 12 | Pebble.addEventListener("webviewclosed", 13 | function(e) { 14 | if (e.response) { 15 | var config = JSON.parse(e.response); 16 | saveLocalData(config); 17 | returnConfigToPebble(); 18 | } 19 | } 20 | ); 21 | 22 | function saveLocalData(config) { 23 | console.log("loadLocalData() " + JSON.stringify(config)); 24 | 25 | localStorage.setItem("seconds", parseInt(config.seconds)); 26 | localStorage.setItem("invert", parseInt(config.invert)); 27 | localStorage.setItem("bluetoothvibe", parseInt(config.bluetoothvibe)); 28 | localStorage.setItem("vibeminutes", parseInt(config.vibeminutes)); 29 | localStorage.setItem("hands", parseInt(config.hands)); 30 | localStorage.setItem("style", parseInt(config.style)); 31 | localStorage.setItem("background", parseInt(config.background)); 32 | localStorage.setItem("timezone", parseInt(config.timezone)); 33 | localStorage.setItem("bigmode", parseInt(config.bigmode)); 34 | localStorage.setItem("dayname", parseInt(config.dayname)); 35 | 36 | loadLocalData(); 37 | } 38 | function loadLocalData() { 39 | mConfig.seconds = parseInt(localStorage.getItem("seconds")); 40 | mConfig.invert = parseInt(localStorage.getItem("invert")); 41 | mConfig.bluetoothvibe = parseInt(localStorage.getItem("bluetoothvibe")); 42 | mConfig.vibeminutes = parseInt(localStorage.getItem("vibeminutes")); 43 | mConfig.hands = parseInt(localStorage.getItem("hands")); 44 | mConfig.style = parseInt(localStorage.getItem("style")); 45 | mConfig.background = parseInt(localStorage.getItem("background")); 46 | mConfig.timezone = parseInt(localStorage.getItem("timezone")); 47 | mConfig.bigmode = parseInt(localStorage.getItem("bigmode")); 48 | mConfig.dayname = parseInt(localStorage.getItem("dayname")); 49 | mConfig.configureUrl = "http://www.mirz.com/Aviatorv2/index3.html"; 50 | 51 | if(isNaN(mConfig.seconds)) { 52 | mConfig.seconds = 1; 53 | } 54 | if(isNaN(mConfig.invert)) { 55 | mConfig.invert = 0; 56 | } 57 | if(isNaN(mConfig.bluetoothvibe)) { 58 | mConfig.bluetoothvibe = 1; 59 | } 60 | if(isNaN(mConfig.vibeminutes)) { 61 | mConfig.vibeminutes = 0; 62 | } 63 | if(isNaN(mConfig.hands)) { 64 | mConfig.hands = 1; 65 | } 66 | if(isNaN(mConfig.style)) { 67 | mConfig.style = 0; 68 | } 69 | if(isNaN(mConfig.background)) { 70 | mConfig.background = 0; 71 | } 72 | if(isNaN(mConfig.timezone)) { 73 | mConfig.timezone = 0; 74 | } 75 | if(isNaN(mConfig.bigmode)) { 76 | mConfig.bigmode = 0; 77 | } 78 | if(isNaN(mConfig.dayname)) { 79 | mConfig.dayname = 0; 80 | } 81 | } 82 | function returnConfigToPebble() { 83 | console.log("Configuration window returned: " + JSON.stringify({ 84 | "seconds":parseInt(mConfig.seconds), 85 | "invert":parseInt(mConfig.invert), 86 | "bluetoothvibe":parseInt(mConfig.bluetoothvibe), 87 | "vibeminutes":parseInt(mConfig.vibeminutes), 88 | "hands":parseInt(mConfig.hands), 89 | "style":parseInt(mConfig.style), 90 | "background":parseInt(mConfig.background), 91 | "timezone":parseInt(mConfig.timezone), 92 | "timezoneOffset":parseInt(TimezoneOffsetSeconds()), 93 | "timezoneLabel":getTimezoneNameAndOffset().label, 94 | "bigmode":parseInt(mConfig.bigmode), 95 | "dayname":parseInt(mConfig.dayname) 96 | })); 97 | 98 | Pebble.sendAppMessage({ 99 | "seconds":parseInt(mConfig.seconds), 100 | "invert":parseInt(mConfig.invert), 101 | "bluetoothvibe":parseInt(mConfig.bluetoothvibe), 102 | "vibeminutes":parseInt(mConfig.vibeminutes), 103 | "hands":parseInt(mConfig.hands), 104 | "style":parseInt(mConfig.style), 105 | "background":parseInt(mConfig.background), 106 | "timezone":parseInt(mConfig.timezone), 107 | "timezoneOffset":parseInt(TimezoneOffsetSeconds()), 108 | "timezoneLabel":getTimezoneNameAndOffset().label, 109 | "bigmode":parseInt(mConfig.bigmode), 110 | "dayname":parseInt(mConfig.dayname) 111 | }); 112 | } 113 | function TimezoneOffsetSeconds() { 114 | // Get the number of seconds to add to convert localtime to utc 115 | //console.log("Timezone: " + new Date().getTimezoneOffset() * 60); 116 | //return new Date().getTimezoneOffset() * 60; 117 | var x = getTimezoneNameAndOffset(); 118 | 119 | //console.log("orig UTC: " + new Date().getTimezoneOffset() * 60); 120 | //console.log("TimezoneOffsetSeconds: " + (new Date().getTimezoneOffset() + (x.hours * 60) * 60)); 121 | 122 | var now = new Date(); 123 | var nowUtc = new Date(now.getTime() + (now.getTimezoneOffset() * 60000)); 124 | 125 | //console.log("UTC: " + nowUtc); 126 | //console.log("TimezoneOffsetMiliSeconds: " + (nowUtc.getTimezoneOffset() + (x.hours * 60) * 3600)); 127 | 128 | var mil = x.hours * 3600000; 129 | 130 | var secondTimezone = new Date(nowUtc.getTime() + mil); 131 | //console.log("secondTimezone: " + secondTimezone); 132 | 133 | //console.log("is DST: " + secondTimezone.dst()); 134 | var secOff = 0; 135 | //if(secondTimezone.dst()) { 136 | // secOff = 1 * 3600000; 137 | //} 138 | 139 | var totalSeconds = ((secondTimezone.getTime() + secOff) - now.getTime()) / 1000; 140 | //console.log("totalSeconds: " + totalSeconds); 141 | return totalSeconds; 142 | } 143 | 144 | function getTimezoneNameAndOffset() { 145 | var hours = 0; 146 | var label = ''; 147 | 148 | switch(parseInt(mConfig.timezone)) { 149 | case 0: 150 | hours = 0; label='GMT'; 151 | break; 152 | case 1: 153 | hours = 0; label='GMT'; 154 | break; 155 | case 2: 156 | hours = 0; label='GMT'; 157 | break; 158 | case 3: 159 | hours = 1; label='GMT +01:00'; 160 | break; 161 | case 4: 162 | hours = 1; label='GMT +01:00'; 163 | break; 164 | case 5: 165 | hours = 1; label='GMT +01:00'; 166 | break; 167 | case 6: 168 | hours = 1; label='GMT +01:00'; 169 | break; 170 | case 7: 171 | hours = 1; label='GMT +01:00'; 172 | break; 173 | case 8: 174 | hours = 2; label='GMT +02:00'; 175 | break; 176 | case 9: 177 | hours = 2; label='GMT +02:00'; 178 | break; 179 | case 10: 180 | hours = 2; label='GMT +02:00'; 181 | break; 182 | case 11: 183 | hours = 2; label='GMT +02:00'; 184 | break; 185 | case 12: 186 | hours = 2; label='GMT +02:00'; 187 | break; 188 | case 13: 189 | hours = 2; label='GMT +02:00'; 190 | break; 191 | case 14: 192 | hours = 2; label='GMT +02:00'; 193 | break; 194 | case 15: 195 | hours = 2; label='GMT +02:00'; 196 | break; 197 | case 16: 198 | hours = 2; label='GMT +02:00'; 199 | break; 200 | case 17: 201 | hours = 3; label='GMT +03:00'; 202 | break; 203 | case 18: 204 | hours = 3; label='GMT +03:00'; 205 | break; 206 | case 19: 207 | hours = 3; label='GMT +03:00'; 208 | break; 209 | case 20: 210 | hours = 3; label='GMT +03:00'; 211 | break; 212 | case 21: 213 | hours = 3; label='GMT +03:00'; 214 | break; 215 | case 22: 216 | hours = 3.5; label='GMT +03:30'; 217 | break; 218 | case 23: 219 | hours = 4; label='GMT +04:00'; 220 | break; 221 | case 24: 222 | hours = 4; label='GMT +04:00'; 223 | break; 224 | case 25: 225 | hours = 4; label='GMT +04:00'; 226 | break; 227 | case 26: 228 | hours = 4; label='GMT +04:00'; 229 | break; 230 | case 27: 231 | hours = 4.5; label='GMT +04:30'; 232 | break; 233 | case 28: 234 | hours = 5; label='GMT +05:00'; 235 | break; 236 | case 29: 237 | hours = 5; label='GMT +05:00'; 238 | break; 239 | case 30: 240 | hours = 5; label='GMT +05:00'; 241 | break; 242 | case 31: 243 | hours = 5.5; label='GMT +05:30'; 244 | break; 245 | case 32: 246 | hours = 5.5; label='GMT +05:30'; 247 | break; 248 | case 33: 249 | hours = 5.75; label='GMT +05:45'; 250 | break; 251 | case 34: 252 | hours = 6; label='GMT +06:00'; 253 | break; 254 | case 35: 255 | hours = 6; label='GMT +06:00'; 256 | break; 257 | case 36: 258 | hours = 6.5; label='GMT +06:30'; 259 | break; 260 | case 37: 261 | hours = 7; label='GMT +07:00'; 262 | break; 263 | case 38: 264 | hours = 7; label='GMT +07:00'; 265 | break; 266 | case 39: 267 | hours = 8; label='GMT +08:00'; 268 | break; 269 | case 40: 270 | hours = 8; label='GMT +08:00'; 271 | break; 272 | case 41: 273 | hours = 8; label='GMT +08:00'; 274 | break; 275 | case 42: 276 | hours = 8; label='GMT +08:00'; 277 | break; 278 | case 43: 279 | hours = 8; label='GMT +08:00'; 280 | break; 281 | case 44: 282 | hours = 9; label='GMT +09:00'; 283 | break; 284 | case 45: 285 | hours = 9; label='GMT +09:00'; 286 | break; 287 | case 46: 288 | hours = 9; label='GMT +09:00'; 289 | break; 290 | case 47: 291 | hours = 9.5; label='GMT +09:30'; 292 | break; 293 | case 48: 294 | hours = 9.5; label='GMT +09:30'; 295 | break; 296 | case 49: 297 | hours = 10; label='GMT +10:00'; 298 | break; 299 | case 50: 300 | hours = 10; label='GMT +10:00'; 301 | break; 302 | case 51: 303 | hours = 10; label='GMT +10:00'; 304 | break; 305 | case 52: 306 | hours = 10; label='GMT +10:00'; 307 | break; 308 | case 53: 309 | hours = 10; label='GMT +10:00'; 310 | break; 311 | case 54: 312 | hours = 11; label='GMT +11:00'; 313 | break; 314 | case 55: 315 | hours = 12; label='GMT +12:00'; 316 | break; 317 | case 56: 318 | hours = 12; label='GMT +12:00'; 319 | break; 320 | case 57: 321 | hours = 13; label='GMT +13:00'; 322 | break; 323 | case 58: 324 | hours = -1; label='GMT -01:00'; 325 | break; 326 | case 59: 327 | hours = -1; label='GMT -01:00'; 328 | break; 329 | case 60: 330 | hours = -2; label='GMT -02:00'; 331 | break; 332 | case 61: 333 | hours = -3; label='GMT -03:00'; 334 | break; 335 | case 62: 336 | hours = -3; label='GMT -03:00'; 337 | break; 338 | case 63: 339 | hours = -3; label='GMT -03:00'; 340 | break; 341 | case 64: 342 | hours = -3; label='GMT -03:00'; 343 | break; 344 | case 65: 345 | hours = -3; label='GMT -03:00'; 346 | break; 347 | case 66: 348 | hours = -3.5; label='GMT -03:30'; 349 | break; 350 | case 67: 351 | hours = -4; label='GMT -04:00'; 352 | break; 353 | case 68: 354 | hours = -4; label='GMT -04:00'; 355 | break; 356 | case 69: 357 | hours = -4; label='GMT -04:00'; 358 | break; 359 | case 70: 360 | hours = -4; label='GMT -04:00'; 361 | break; 362 | case 71: 363 | hours = -4.5; label='GMT -04:30'; 364 | break; 365 | case 72: 366 | hours = -5; label='GMT -05:00'; 367 | break; 368 | case 73: 369 | hours = -5; label='GMT -05:00'; 370 | break; 371 | case 74: 372 | hours = -5; label='GMT -05:00'; 373 | break; 374 | case 75: 375 | hours = -6; label='GMT -06:00'; 376 | break; 377 | case 76: 378 | hours = -6; label='GMT -06:00'; 379 | break; 380 | case 77: 381 | hours = -6; label='GMT -06:00'; 382 | break; 383 | case 78: 384 | hours = -6; label='GMT -06:00'; 385 | break; 386 | case 79: 387 | hours = -7; label='GMT -07:00'; 388 | break; 389 | case 80: 390 | hours = -7; label='GMT -07:00'; 391 | break; 392 | case 81: 393 | hours = -7; label='GMT -07:00'; 394 | break; 395 | case 82: 396 | hours = -8; label='GMT -08:00'; 397 | break; 398 | case 83: 399 | hours = -8; label='GMT -08:00'; 400 | break; 401 | case 84: 402 | hours = -9; label='GMT -09:00'; 403 | break; 404 | case 85: 405 | hours = -10; label='GMT -10:00'; 406 | break; 407 | case 86: 408 | hours = -11; label='GMT -11:00'; 409 | break; 410 | case 87: 411 | hours = -12; label='GMT -12:00'; 412 | break; 413 | } 414 | return { 415 | hours: hours, 416 | label: label 417 | }; 418 | 419 | } 420 | 421 | Date.prototype.stdTimezoneOffset = function() { 422 | var jan = new Date(this.getFullYear(), 0, 1); 423 | var jul = new Date(this.getFullYear(), 6, 1); 424 | return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); 425 | }; 426 | 427 | Date.prototype.dst = function() { 428 | return this.getTimezoneOffset() < this.stdTimezoneOffset(); 429 | }; 430 | 431 | -------------------------------------------------------------------------------- /src/math.c: -------------------------------------------------------------------------------- 1 | //Taken from Michael Ehrmann source code of SunClock https://github.com/mehrmann/pebble-sunclock 2 | #include "math.h" 3 | 4 | /* 5 | * loosely based on 6 | * - http://stackoverflow.com/questions/11261170/c-and-maths-fast-approximation-of-a-trigonometric-function 7 | * - http://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi 8 | */ 9 | 10 | #define SQRT_MAGIC_F 0x5f3759df 11 | float my_sqrt(const float x) 12 | { 13 | const float xhalf = 0.5f*x; 14 | 15 | union // get bits for floating value 16 | { 17 | float x; 18 | int i; 19 | } u; 20 | u.x = x; 21 | u.i = SQRT_MAGIC_F - (u.i >> 1); // gives initial guess y0 22 | return x*u.x*(1.5f - xhalf*u.x*u.x);// Newton step, repeating increases accuracy 23 | } 24 | 25 | float my_floor(float x) 26 | { 27 | return ((int)x); 28 | } 29 | 30 | float my_fabs(float x) 31 | { 32 | if (x<0) return -x; 33 | return x; 34 | } 35 | 36 | float my_atan(float x) 37 | { 38 | if (x>0) 39 | { 40 | return (M_PI/2)*(0.596227*x + x*x)/(1 + 2*0.596227*x + x*x); 41 | } 42 | else 43 | { 44 | return -(my_atan(-x)); 45 | } 46 | } 47 | 48 | /* not quite rint(), i.e. results not properly rounded to nearest-or-even */ 49 | float my_rint (float x) 50 | { 51 | float t = my_floor (my_fabs(x) + 0.5); 52 | return (x < 0.0) ? -t : t; 53 | } 54 | 55 | /* minimax approximation to cos on [-pi/4, pi/4] with rel. err. ~= 7.5e-13 */ 56 | float cos_core (float x) 57 | { 58 | float x8, x4, x2; 59 | x2 = x * x; 60 | x4 = x2 * x2; 61 | x8 = x4 * x4; 62 | /* evaluate polynomial using Estrin's scheme */ 63 | return (-2.7236370439787708e-7 * x2 + 2.4799852696610628e-5) * x8 + 64 | (-1.3888885054799695e-3 * x2 + 4.1666666636943683e-2) * x4 + 65 | (-4.9999999999963024e-1 * x2 + 1.0000000000000000e+0); 66 | } 67 | 68 | /* minimax approximation to sin on [-pi/4, pi/4] with rel. err. ~= 5.5e-12 */ 69 | float sin_core (float x) 70 | { 71 | float x4, x2; 72 | x2 = x * x; 73 | x4 = x2 * x2; 74 | /* evaluate polynomial using a mix of Estrin's and Horner's scheme */ 75 | return ((2.7181216275479732e-6 * x2 - 1.9839312269456257e-4) * x4 + 76 | (8.3333293048425631e-3 * x2 - 1.6666666640797048e-1)) * x2 * x + x; 77 | } 78 | 79 | /* minimax approximation to arcsin on [0, 0.5625] with rel. err. ~= 1.5e-11 */ 80 | float asin_core (float x) 81 | { 82 | float x8, x4, x2; 83 | x2 = x * x; 84 | x4 = x2 * x2; 85 | x8 = x4 * x4; 86 | /* evaluate polynomial using a mix of Estrin's and Horner's scheme */ 87 | return (((4.5334220547132049e-2 * x2 - 1.1226216762576600e-2) * x4 + 88 | (2.6334281471361822e-2 * x2 + 2.0596336163223834e-2)) * x8 + 89 | (3.0582043602875735e-2 * x2 + 4.4630538556294605e-2) * x4 + 90 | (7.5000364034134126e-2 * x2 + 1.6666666300567365e-1)) * x2 * x + x; 91 | } 92 | 93 | /* relative error < 7e-12 on [-50000, 50000] */ 94 | float my_sin (float x) 95 | { 96 | float q, t; 97 | int quadrant; 98 | /* Cody-Waite style argument reduction */ 99 | q = my_rint (x * 6.3661977236758138e-1); 100 | quadrant = (int)q; 101 | t = x - q * 1.5707963267923333e+00; 102 | t = t - q * 2.5633441515945189e-12; 103 | if (quadrant & 1) { 104 | t = cos_core(t); 105 | } else { 106 | t = sin_core(t); 107 | } 108 | return (quadrant & 2) ? -t : t; 109 | } 110 | 111 | float my_cos(float x) 112 | { 113 | return my_sin(x + (M_PI/2)); 114 | } 115 | 116 | /* relative error < 2e-11 on [-1, 1] */ 117 | float my_acos (float x) 118 | { 119 | float xa, t; 120 | xa = my_fabs (x); 121 | /* arcsin(x) = pi/2 - 2 * arcsin (sqrt ((1-x) / 2)) 122 | * arccos(x) = pi/2 - arcsin(x) 123 | * arccos(x) = 2 * arcsin (sqrt ((1-x) / 2)) 124 | */ 125 | if (xa > 0.5625) { 126 | t = 2.0 * asin_core (my_sqrt (0.5 * (1.0 - xa))); 127 | } else { 128 | t = 1.5707963267948966 - asin_core (xa); 129 | } 130 | /* arccos (-x) = pi - arccos(x) */ 131 | return (x < 0.0) ? (3.1415926535897932 - t) : t; 132 | } 133 | 134 | float my_asin (float x) 135 | { 136 | return (M_PI/2) - my_acos(x); 137 | } 138 | 139 | float my_tan(float x) 140 | { 141 | return my_sin(x) / my_cos(x); 142 | } -------------------------------------------------------------------------------- /src/math.h: -------------------------------------------------------------------------------- 1 | //Taken from Michael Ehrmann source code of SunClock https://github.com/mehrmann/pebble-sunclock 2 | #pragma once 3 | 4 | #define M_PI 3.141592653589793 5 | float my_sqrt(const float x); 6 | float my_floor(float x); 7 | float my_fabs(float x); 8 | float my_atan(float x); 9 | float my_rint (float x); 10 | float my_sin (float x); 11 | float my_cos(float x); 12 | float my_acos (float x); 13 | float my_asin (float x); 14 | float my_tan(float x); -------------------------------------------------------------------------------- /wscript: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # This file is the default set of rules to compile a Pebble project. 4 | # 5 | # Feel free to customize this to your needs. 6 | # 7 | 8 | import os.path 9 | 10 | top = '.' 11 | out = 'build' 12 | 13 | def options(ctx): 14 | ctx.load('pebble_sdk') 15 | 16 | def configure(ctx): 17 | ctx.load('pebble_sdk') 18 | 19 | def build(ctx): 20 | ctx.load('pebble_sdk') 21 | 22 | build_worker = os.path.exists('worker_src') 23 | binaries = [] 24 | 25 | for p in ctx.env.TARGET_PLATFORMS: 26 | ctx.set_env(ctx.all_envs[p]) 27 | ctx.set_group(ctx.env.PLATFORM_NAME) 28 | app_elf='{}/pebble-app.elf'.format(ctx.env.BUILD_DIR) 29 | ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'), 30 | target=app_elf) 31 | 32 | if build_worker: 33 | worker_elf='{}/pebble-worker.elf'.format(ctx.env.BUILD_DIR) 34 | binaries.append({'platform': p, 'app_elf': app_elf, 'worker_elf': worker_elf}) 35 | ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'), 36 | target=worker_elf) 37 | else: 38 | binaries.append({'platform': p, 'app_elf': app_elf}) 39 | 40 | ctx.set_group('bundle') 41 | ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js')) 42 | --------------------------------------------------------------------------------