├── .gitignore ├── LICENSE ├── Others ├── Toolbar.sketch ├── ToolbarTemplate.sketch ├── icon-grid.pxm ├── icon.png ├── icon.pxm ├── icon_256.png ├── presentation.png ├── presentation.pxm ├── screen-export.pxm ├── screen-list.pxm ├── screen1.pxm ├── screen2.pxm └── screen3.pxm ├── README.md ├── ScreenToLayers.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ScreenToLayers ├── Interfaces │ └── Base.lproj │ │ ├── ListWindow.xib │ │ ├── MainMenu.xib │ │ ├── Preferences.xib │ │ └── Presentation.xib ├── Resources │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── icon_128x128.png │ │ │ ├── icon_128x128@2x.png │ │ │ ├── icon_16x16.png │ │ │ ├── icon_16x16@2x.png │ │ │ ├── icon_256x256.png │ │ │ ├── icon_256x256@2x.png │ │ │ ├── icon_32x32.png │ │ │ ├── icon_32x32@2x.png │ │ │ ├── icon_512x512.png │ │ │ └── icon_512x512@2x.png │ │ ├── ButtonTemplate.imageset │ │ │ ├── Contents.json │ │ │ ├── ToolbarTemplate.png │ │ │ └── ToolbarTemplate@2x.png │ │ ├── Contents.json │ │ ├── Icon.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_512x512.png │ │ │ └── icon_512x512@2x.png │ │ └── ScreenMenubar.imageset │ │ │ ├── Contents.json │ │ │ ├── ScreenMenubar.png │ │ │ └── ScreenMenubar@2x.png │ ├── Sounds │ │ └── CaptureEndSound.aiff │ └── Supporting Files │ │ ├── Info.plist │ │ └── main.m ├── ScreenToLayers.entitlements └── Sources │ ├── Application │ ├── AppController.h │ ├── AppController.m │ ├── Constants.h │ ├── Constants.m │ ├── ListController.h │ ├── ListController.m │ ├── Preferences.h │ ├── Preferences.m │ ├── Presentation.h │ ├── Presentation.m │ ├── ScreenGraber.h │ ├── ScreenGraber.m │ ├── WhiteView.h │ └── WhiteView.m │ └── PSD writer │ ├── NSDataPSDAdditions.h │ ├── NSDataPSDAdditions.m │ ├── PSDLayer.h │ ├── PSDLayer.m │ ├── PSDWriter.h │ └── PSDWriter.m ├── ScreenToLayersHelper.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ScreenToLayersHelper ├── AppDelegate.h ├── AppDelegate.m ├── Info.plist ├── MainMenu.xib ├── ScreenToLayersHelper.entitlements └── main.m ├── ScreenToLayersTests ├── Info.plist └── ScreenToLayersTests.m └── Website ├── assets ├── fonts │ ├── elegant-icons │ │ └── ElegantIcons.ttf │ ├── lato-black │ │ ├── lato-black-0fdcfb7bc888d2aff696dda853bc4ddc8d0cdf8655f7cab2f0263bbe189e160d.woff │ │ ├── lato-black-62398f940a9564361022ba6d5fbbaad7cb600b3d7ef13a259a7bc4c859dd4f44.ttf │ │ ├── lato-black-b9d6daf4817c613cfaeaeffc594696f366eca04e299a18d7bc5ef7ac5bb250c4.svg │ │ ├── lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4-.eot │ │ ├── lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4.eot │ │ └── lato-black-ff00636ea86b2c0d42f9b810b4f8304468ede38a3bd1bb14ac85086c879123f5.woff2 │ ├── lato-blackitalic │ │ ├── lato-blackitalic-5c30baab619437ce5d1db90496ba62e511194b0247aaa0d9d4eb1c7eff9e9cb9.woff │ │ ├── lato-blackitalic-a325dc2f6a88577f0c28ea52529b3cb5fc93392b573ed3d34195b5c0e8ffbfcf.svg │ │ ├── lato-blackitalic-b91fc91ef31bcedf97c528d7ecc3b2cfc9a3f6201017827647641a5fdcf15332.woff2 │ │ ├── lato-blackitalic-be00fa70983ec52b18b98e1b9f172432ee941c62ceddd06e945a71f8f30b38f7.ttf │ │ ├── lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91-.eot │ │ └── lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91.eot │ ├── lato-bold │ │ ├── lato-bold-2db60403ee96a301b6290c255ef74653fe8dc2b4251ee66ed4e939cd05dbc84e.woff2 │ │ ├── lato-bold-4013e068df10593a69fae75d89a24b170951500db393cf66f89dd2eff4325bad.ttf │ │ ├── lato-bold-40de0826765a36cf9b52567582ea9bcaabf0ee6fa41e29e0b19da7c87663152d.svg │ │ ├── lato-bold-4c04f7890211bca9a31919ee49e1250835ab842c3a0a6321ce7af1e3b38beee2.woff │ │ ├── lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d-.eot │ │ └── lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d.eot │ ├── lato-bolditalic │ │ ├── lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e-.eot │ │ ├── lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e.eot │ │ ├── lato-bolditalic-43f0b7fb26b7aa057838431c48b21ac94aef1273ff444e8be594ebc7df8b70bf.svg │ │ ├── lato-bolditalic-70f233b8c3d0ca4baa08edb05d0aad645ebd8785f3b9008a7ddb0cdbc0999355.woff │ │ ├── lato-bolditalic-7c82caec73fedc2f2a2ac7b555a18d996a3c002e4c8bf4ad98f5eabcc00911a6.woff2 │ │ └── lato-bolditalic-cbe6e3a67d25024006b81fc63c7c6f939cd6e8b6710abe1b7f57a71f8fb0d2cd.ttf │ ├── lato-hairline │ │ ├── lato-hairline-0383396e9c2fa6a01ddd23a6bbe2c2e080c949c4870e7a2efa0aa1df65ce2d3f.ttf │ │ ├── lato-hairline-04e4ac380098f2d2f2861f03b0758dff9a649219cd2042bba8cabe23b476dd83.svg │ │ ├── lato-hairline-8cae7ee6d8b1c9b4931074bc6db6d4d91c4cf58b09a6fd01ea1e3111a23bde6f.woff2 │ │ ├── lato-hairline-8cd6e1c4ff74bd2a6a487cd6010a01d15550fab64e1301e0db7ba7cd475502c1.woff │ │ ├── lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61-.eot │ │ └── lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61.eot │ ├── lato-hairlineitalic │ │ ├── lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73-.eot │ │ ├── lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73.eot │ │ ├── lato-hairlineitalic-13b8e2ec7c8bdb58c6b23559e9b361367d80167d2e630f413bc4d381aff98f1f.woff │ │ ├── lato-hairlineitalic-531ef4d2da6e541d10fb2ec2b75c5136cfee31965fcf1184b70ada55c88e82e4.ttf │ │ ├── lato-hairlineitalic-b7d7d0e1816bc776d99eda748bc01312005fd497e3f5b91573cc291ef5ddb2ea.woff2 │ │ └── lato-hairlineitalic-f0095859702ef7e490a6682bda0a1b7c148afc7c31c067d951d7b7f6aaef1c07.svg │ ├── lato-heavy │ │ ├── lato-heavy-26e51949df663e17fe24e240368aa46e6a269cf07ce45cbfee2bf6d10efa712b.woff2 │ │ ├── lato-heavy-3f519229220cb477506e28c855bef4bc0eca6978807c6da90745601e30e2a7ba.ttf │ │ ├── lato-heavy-8e740b41353f909f7611131ca23a91b0ae951f01f3d625b3f7b16ea1ade2a9f9.svg │ │ ├── lato-heavy-b61b8c1f4ecea7b5b6a80c0e2db37c306e8c3afc280e6bf3fff8fb3f36f225aa.woff │ │ ├── lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7-.eot │ │ └── lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7.eot │ ├── lato-heavyitalic │ │ ├── lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5-.eot │ │ ├── lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5.eot │ │ ├── lato-heavyitalic-1e9c13e0236e0509dd5e7f53eb8f0588a8a6ce56de853263412a7fb3926394cf.woff2 │ │ ├── lato-heavyitalic-303ad9fdca6b278c230dac7bc076a8fa28b69c95249a6c62c48b73fa2da9a404.woff │ │ ├── lato-heavyitalic-910a7d953f7f85ab9baf9a24ed474a1b232b601dda7e698e5189e77fb531fa25.ttf │ │ └── lato-heavyitalic-bde5dac99fac2801ff7e82e94932592a96acb72098ecf2d1dfdd0fe6a37980ff.svg │ ├── lato-italic │ │ ├── lato-italic-09c7fca6b6ec95d8caf5a3cd86bb625f4a943dca54d0d1bd9cf4ee4296d3b434.ttf │ │ ├── lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f-.eot │ │ ├── lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f.eot │ │ ├── lato-italic-99c728c57c59c376c1fa76bdfcf214c88327d12f7049d579ed5df8d7acf996f9.svg │ │ ├── lato-italic-e37ec1819c1ab85df6e2069a90d2d686ce211cf1d83e70a1ff2c3eed66b679da.woff2 │ │ └── lato-italic-fdccaa222969116965e47e9caee632698eba2e10263b4ece35e0c35ef5ef7013.woff │ ├── lato-light │ │ ├── lato-light-2db698035576dcb0ba8a5c8c70d53b553b92882c9b1f5a9483618b98aa3a9fb1.woff │ │ ├── lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c-.eot │ │ ├── lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c.eot │ │ ├── lato-light-4c8fca932790d59f62df83d77cf1c4ec3de1b9a372f61e81a1746b62fba36ed7.woff2 │ │ ├── lato-light-4d552c3704d63389f5da8f4e8ce48606662d9ff9a4add6984f367d086df547a9.svg │ │ └── lato-light-7efd0b09b9f1934d99449269dbb4ec5b8ca917b18fb18cfd0852c48a05d32cff.ttf │ ├── lato-lightitalic │ │ ├── lato-lightitalic-2423373fcad3126d629d73bde440a05be0af07b8e703b06cf754aafb92121861.svg │ │ ├── lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a-.eot │ │ ├── lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a.eot │ │ ├── lato-lightitalic-d9fc1c1da023580642e39b9ef87c2cfbcc1d6508919306274fee3403dc0dc159.woff2 │ │ └── lato-lightitalic-e33518d1874f4cb4a004d52f1ef9f17b766422213249a225990cc229c938d86d.ttf │ ├── lato-medium │ │ ├── lato-medium-83f6d6134d3121d9ac20cadff1b79dfbfe7593d78edaaa1bd2c0014e4d6bb51f.woff │ │ ├── lato-medium-88383bfbcdcf3e82320014f9810df449dcdeddac988ac23732dfc70ec1b7d77d.svg │ │ ├── lato-medium-af767dc73c5b662830c2ac04403a801bfb1ac58c61a54879e0cf7bfdf7204648.ttf │ │ ├── lato-medium-c199213882b79fe118e73b1f490b534a2be2eb6485bccfd8137b934a1cc66cbd.woff2 │ │ ├── lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7-.eot │ │ └── lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7.eot │ ├── lato-mediumitalic │ │ ├── lato-mediumitalic-4242fdcecc77250d348cb9d247df5ef3fd7c18bd5ed5a7fb1f9c24150c8a7500.woff │ │ ├── lato-mediumitalic-525c8ca6df88d1a3207eabfb0cdb590918c1228d0969482e1ad0e1b35d58c349.ttf │ │ ├── lato-mediumitalic-5b6e2a34b68e9a2a4b3dc827be88e25c74d92e41cd236e44f5c2136855703e0d.svg │ │ ├── lato-mediumitalic-8f447edcd2d39ee7af8aa0b06d04a8fd2e27dbff93b625c0e6e9f3d8b04e9a39.woff2 │ │ ├── lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960-.eot │ │ └── lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960.eot │ ├── lato-regular │ │ ├── lato-regular-4d1b04750516461935cc4380bd441308d5eae5f286e039a05993a7ab64cfdef3.ttf │ │ ├── lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4-.eot │ │ ├── lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4.eot │ │ ├── lato-regular-bac8fd7529ad14199431bf9b56c388af416c02c1680cfa398cfb9cedcdcd3eef.woff │ │ ├── lato-regular-ce4692a8bacdb88a0718e13301e09789374fb33db26ca651f90e224fbadf8864.svg │ │ └── lato-regular-dc3da5f3b2066ffd80e16409739c3f46b854159b3da3c51add3f1575e9871ee6.woff2 │ ├── lato-semibold │ │ ├── lato-semibold-15f0dbfdc7e0142e35e0cfad279b9162494ebe5d2d2f0dcd19b079c4e4a48682.woff │ │ ├── lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3-.eot │ │ ├── lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3.eot │ │ ├── lato-semibold-4c234cd6a67e6daa59cf45272e0c8b90a7b58945157de68f8dd34ef09ae49b4e.svg │ │ ├── lato-semibold-7fe01f8fb9483d0cb5c8906d05a67b9e507e103bae774432ca46969eea5c232b.ttf │ │ └── lato-semibold-f8f3aac8450bf098f51c3592ac8183464224256f8e46d3859c6a76cc11d59474.woff2 │ ├── lato-semibolditalic │ │ ├── lato-semibolditalic-6acaf70fafb34a047b79a7e8f74d4dc73aba0f535de13001e6fc774cbda44df4.woff │ │ ├── lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49-.eot │ │ ├── lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49.eot │ │ ├── lato-semibolditalic-bd09c611a72e6a286889bf430371e34bd7492e9e219366d55f977aea27beb549.woff2 │ │ ├── lato-semibolditalic-d71659bee75208d433fb0739196567820055dfdde8464fedd54072c074dffa9a.ttf │ │ └── lato-semibolditalic-e69f2b727bec0eb1a9f2f26e5c0e7bdf2968854afc0368c6200a0ed0b199c28a.svg │ ├── lato-thin │ │ ├── lato-thin-3805c2094ccefe9effe129d67fe26d14c950af5564696099c6e02e7ef3e1c127.woff2 │ │ ├── lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3-.eot │ │ ├── lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3.eot │ │ ├── lato-thin-8f2ab9beeb37a5ac9123b8ae8a532f49bd86a3e6232bae9c7e45666bce8ef632.svg │ │ ├── lato-thin-cf486941963fd625a34b4502f3eaa305856fc2441193a5f8c7aa86ede26153f1.ttf │ │ └── lato-thin-d1a9b702aab8df85f75db13a4d5d5b70949eb8211f16ceda058efbd6c47bf681.woff │ └── lato-thinitalic │ │ ├── lato-thinitalic-4d6857db5ccf5ae8493c776a05700f28dd77ba206bceb0d5dc1b2c0ad1b85e40.woff2 │ │ ├── lato-thinitalic-5c8b705d5ef0fe26552ee5224c2cf1150a48697c7b5799b52ac3c3d0e7a49cbc.ttf │ │ ├── lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e-.eot │ │ ├── lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e.eot │ │ ├── lato-thinitalic-b9d520845392f53b55a10c8fe53bb548efeb81163d130677e834457afcbe3c9c.woff │ │ └── lato-thinitalic-bdc13425b84ab24615200757794160da2a214a9b35716f1153c778b011b58535.svg ├── images │ ├── apple-logo.svg │ ├── cover.jpg │ ├── download-logo.svg │ ├── github-logo.svg │ ├── icon_128x128.png │ ├── icon_128x128@2x.png │ ├── icon_16x16.png │ ├── icon_16x16@2x.png │ ├── icon_256x256.png │ ├── icon_256x256@2x.png │ ├── icon_32x32.png │ ├── icon_32x32@2x.png │ ├── icon_512x512.png │ ├── icon_512x512@2x.png │ ├── screen-export.png │ ├── screen-export@2x.png │ ├── screen-list.png │ └── screen-list@2x.png └── stylesheets │ └── style.css ├── downloads ├── screentolayers-presskit.zip └── screentolayers-presskit │ ├── AppStore │ ├── screen1.png │ ├── screen2.png │ └── screen3.png │ ├── Icons │ ├── icon_128x128.png │ ├── icon_128x128@2x.png │ ├── icon_16x16.png │ ├── icon_16x16@2x.png │ ├── icon_256x256.png │ ├── icon_256x256@2x.png │ ├── icon_32x32.png │ ├── icon_32x32@2x.png │ ├── icon_512x512.png │ └── icon_512x512@2x.png │ └── Screenshots │ ├── screen-export.png │ └── screen-list.png └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | .DS_Store 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Jeremy Vizzini 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Others/Toolbar.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/Toolbar.sketch -------------------------------------------------------------------------------- /Others/ToolbarTemplate.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/ToolbarTemplate.sketch -------------------------------------------------------------------------------- /Others/icon-grid.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/icon-grid.pxm -------------------------------------------------------------------------------- /Others/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/icon.png -------------------------------------------------------------------------------- /Others/icon.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/icon.pxm -------------------------------------------------------------------------------- /Others/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/icon_256.png -------------------------------------------------------------------------------- /Others/presentation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/presentation.png -------------------------------------------------------------------------------- /Others/presentation.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/presentation.pxm -------------------------------------------------------------------------------- /Others/screen-export.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/screen-export.pxm -------------------------------------------------------------------------------- /Others/screen-list.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/screen-list.pxm -------------------------------------------------------------------------------- /Others/screen1.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/screen1.pxm -------------------------------------------------------------------------------- /Others/screen2.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/screen2.pxm -------------------------------------------------------------------------------- /Others/screen3.pxm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Others/screen3.pxm -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ScreenToLayers for macOS 2 | 3 | ![Application icon](./Others/presentation.png) 4 | 5 | ## Introduction 6 | 7 | **ScreenToLayers** is a macOS application to easily capture your screen as a layered PSD file. This idea is not mine and comes from a great application named [ScreenShot PSD](https://itunes.apple.com/us/app/screenshot-psd/id489880259?ls=1&mt=12). However the app is not optimized for El capitan and doesn't support retina screen. That is why I made my own open source alternative. 8 | 9 | The actual version is very simple and only meets my own requirements. However, I look forward about new features and contribution from the community (programmers and designers). 10 | 11 | The application uses some not very well-known APIs. If you want to register your application at startup or if you need to create a persistent file access due to the sandboxing of the AppStore, some code portions will help you to understand how to. 12 | 13 | ## Installation 14 | 15 | The simplest way to get the latest release of **ScreenToLayers** is to download the application through the [Mac AppStore](https://itunes.apple.com/us/app/screentolayers/id1077317077?ls=1&mt=8). The application is totally free and it is updated when major changes are made. 16 | 17 | ## Compilation 18 | 19 | The application was compiled and tested with Xcode 7 on Mac Sierra. The project requires macOS 10.10 and used ARC and Cocoa. 20 | 21 | To compile, you only have to open `ScreenToLayers.xcodeproj` and run. 22 | 23 | ## Contribution 24 | 25 | If you have ideas or if you found bugs, I encourage you to open a pull-issue. 26 | 27 | If you are a developer and/or a designer, you can also contribute to the project by submitting pull-requests on the dev branch. The application was written in Objective-C to simplify the use of the low level API. I don't want to mix Objective-C and Swift for small project like this one. Please try to follow this rule and keep the actual guide style. 28 | 29 | ## About 30 | 31 | My name is Jeremy Vizzini and you can read more about me on [jeremyvizzini.com](http://jeremyvizzini.com). 32 | 33 | ## References 34 | 35 | * Application website : [here](http://screentolayersapp.com) 36 | * Mac AppStore page : [here](https://github.com/jeremyvizzini/ScreenToLayers) 37 | * Apple sample demonstrating the CGWindow API : [Sample](https://developer.apple.com/library/prerelease/content/samplecode/SonOfGrab/Introduction/Intro.html). 38 | 39 | ## License 40 | 41 | ScreenToLayers is released under a MIT license. See the LICENSE file for more information. 42 | -------------------------------------------------------------------------------- /ScreenToLayers.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScreenToLayers/Interfaces/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /ScreenToLayers/Interfaces/Base.lproj/Preferences.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 42 | 53 | 64 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 95 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /ScreenToLayers/Interfaces/Base.lproj/Presentation.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ScreenToLayers is located in the menu bar to give you a quick access everywhere. Moreover, you can instantly capture your screen by using the shortcut ⌘⇧5. 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Futhermore, the application is open-source. If your need features and / or you are a designer or a programmer, you can contribute to the project via GitHub. You can also email if you need help. 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 88 | 99 | 110 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon_16x16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon_16x16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon_32x32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon_32x32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon_128x128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon_128x128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon_256x256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon_256x256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon_512x512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon_512x512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ButtonTemplate.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ToolbarTemplate.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ToolbarTemplate@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ButtonTemplate.imageset/ToolbarTemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/ButtonTemplate.imageset/ToolbarTemplate.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ButtonTemplate.imageset/ToolbarTemplate@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/ButtonTemplate.imageset/ToolbarTemplate@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/Icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_512x512.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icon_512x512@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/Icon.imageset/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/Icon.imageset/icon_512x512.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/Icon.imageset/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/Icon.imageset/icon_512x512@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ScreenMenubar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ScreenMenubar.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ScreenMenubar@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ScreenMenubar.imageset/ScreenMenubar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/ScreenMenubar.imageset/ScreenMenubar.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Assets.xcassets/ScreenMenubar.imageset/ScreenMenubar@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Assets.xcassets/ScreenMenubar.imageset/ScreenMenubar@2x.png -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Sounds/CaptureEndSound.aiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/ScreenToLayers/Resources/Sounds/CaptureEndSound.aiff -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.3 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 5 23 | LSApplicationCategoryType 24 | public.app-category.developer-tools 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | LSUIElement 28 | 29 | NSHumanReadableCopyright 30 | Copyright © 2016 Jeremy Vizzini. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /ScreenToLayers/Resources/Supporting Files/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini on 17/01/16. 6 | // Copyright © 2016 Jeremy Vizzini. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ScreenToLayers/ScreenToLayers.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.assets.pictures.read-write 8 | 9 | com.apple.security.files.bookmarks.app-scope 10 | 11 | com.apple.security.files.user-selected.read-write 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/AppController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppController.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppController : NSObject 13 | 14 | #pragma mark Actions 15 | 16 | - (IBAction)grabScreenshot:(id)sender; 17 | - (IBAction)grabScreenshotWithDelay:(id)sender; 18 | - (IBAction)openOutputsFolder:(id)sender; 19 | - (IBAction)showWindowsList:(id)sender; 20 | 21 | - (IBAction)contactCustomerSupport:(id)sender; 22 | - (IBAction)openApplicationWebsite:(id)sender; 23 | - (IBAction)openAppStorePage:(id)sender; 24 | - (IBAction)openGitHubPage:(id)sender; 25 | 26 | - (IBAction)showPreferences:(id)sender; 27 | - (IBAction)showPresentation:(id)sender; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/AppController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppController.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "AppController.h" 10 | #import "ListController.h" 11 | #import "ScreenGraber.h" 12 | #import "Presentation.h" 13 | #import "PSDWriter.h" 14 | #import "Preferences.h" 15 | #import "Constants.h" 16 | 17 | #pragma mark AppController Private 18 | 19 | @interface AppController () 20 | 21 | @property (weak) IBOutlet NSMenu *statusMenu; 22 | @property (strong) NSStatusItem *statusItem; 23 | @property (strong) ScreenGraber *graber; 24 | @property (strong) NSSound *flashSound; 25 | @property (strong) NSSound *timerSound; 26 | @property (assign) NSInteger timerCount; 27 | @property (strong) NSImage *defaultImage; 28 | @property (strong) NSImage *progressImage; 29 | @property (assign) CGFloat progressDegrees; 30 | 31 | @end 32 | 33 | #pragma mark AppController Implementation 34 | 35 | @implementation AppController 36 | 37 | #pragma mark Initializers 38 | 39 | - (instancetype)init { 40 | self = [super init]; 41 | if (self) { 42 | self.timerCount = -1; 43 | self.graber = [[ScreenGraber alloc] init]; 44 | self.graber.cursorOnTop = true; 45 | 46 | self.flashSound = [NSSound soundNamed:@"CaptureEndSound"]; 47 | self.timerSound = [NSSound soundNamed:@"Tink"]; 48 | self.timerSound.volume = 0.3; 49 | 50 | self.defaultImage = [NSImage imageNamed:@"ButtonTemplate"]; 51 | [self updateProgressDegrees:nil]; 52 | } 53 | return self; 54 | } 55 | 56 | #pragma mark NSApplicationDelegate 57 | 58 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { 59 | [Preferences setupDefaults]; 60 | 61 | [self setupStatusItem]; 62 | [self registerHotKeys]; 63 | 64 | if ([Preferences launchCount] == 1) { 65 | [self showPreferences:nil]; 66 | [self showPresentation:nil]; 67 | } 68 | } 69 | 70 | #pragma mark Hotkeys 71 | 72 | static OSStatus _hotKeyEventHandler(EventHandlerCallRef h, EventRef event, void *p) { 73 | EventHotKeyID hotKeyID; 74 | OSStatus err = GetEventParameter(event, 75 | kEventParamDirectObject, 76 | typeEventHotKeyID, 77 | nil, 78 | sizeof(EventHotKeyID), 79 | nil, 80 | &hotKeyID); 81 | if (err) 82 | return err; 83 | 84 | switch (hotKeyID.id) { 85 | case 1: [NSApp sendAction:@selector(grabScreenshot:) to:nil from:nil]; break; 86 | case 2: [NSApp sendAction:@selector(grabScreenshotWithDelay:) to:nil from:nil]; break; 87 | default: break; 88 | } 89 | return YES; 90 | } 91 | 92 | - (void)registerHotKeys { 93 | EventHotKeyRef hotKeyRef; 94 | EventHotKeyID hotKeyID; 95 | EventTypeSpec eventType = {kEventClassKeyboard, kEventHotKeyPressed}; 96 | 97 | InstallApplicationEventHandler(&_hotKeyEventHandler, 1, &eventType, NULL, NULL); 98 | EventTargetRef target = GetApplicationEventTarget(); 99 | 100 | hotKeyID.signature='htk1'; 101 | hotKeyID.id = 1; 102 | RegisterEventHotKey(kVK_ANSI_5, cmdKey+shiftKey, hotKeyID, target, 0, &hotKeyRef); 103 | 104 | hotKeyID.signature='htk2'; 105 | hotKeyID.id = 2; 106 | RegisterEventHotKey(kVK_ANSI_6, cmdKey+shiftKey, hotKeyID, target, 0, &hotKeyRef); 107 | 108 | } 109 | 110 | #pragma mark Status item 111 | 112 | - (void)setupStatusItem { 113 | NSStatusBar *sb = [NSStatusBar systemStatusBar]; 114 | self.statusItem = [sb statusItemWithLength:26]; 115 | self.statusItem.image = self.defaultImage; 116 | self.statusItem.menu = self.statusMenu; 117 | self.statusItem.highlightMode = YES; 118 | } 119 | 120 | - (void)updateBarWithTimer { 121 | self.statusItem.image = nil; 122 | self.statusItem.title = [NSString stringWithFormat:@"%ld", self.timerCount]; 123 | } 124 | 125 | - (void)updateBarWithProgress { 126 | self.statusItem.image = self.progressImage; 127 | self.statusItem.title = nil; 128 | } 129 | 130 | - (void)restoreBarWithImage { 131 | self.statusItem.image = self.defaultImage; 132 | self.statusItem.title = nil; 133 | } 134 | 135 | #pragma mark Screenshot 136 | 137 | - (NSURL *)screenshotsDirectoryURL { 138 | NSFileManager *fm = [NSFileManager defaultManager]; 139 | NSURL *directoryURL = [Preferences exportDirectoryURL]; 140 | [fm createDirectoryAtURL:directoryURL withIntermediateDirectories:YES attributes:nil error:nil]; 141 | return directoryURL; 142 | } 143 | 144 | - (NSString *)filenameForCurrentDate { 145 | NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init]; 146 | dateFormatter.dateFormat = @"yyyy-MM-dd HH-mm-ss"; 147 | return [dateFormatter stringFromDate:[NSDate date]]; 148 | } 149 | 150 | - (NSURL *)psdURLForCurrentDate { 151 | NSURL *dirURL = [self screenshotsDirectoryURL]; 152 | NSString *filename = [self filenameForCurrentDate]; 153 | NSURL *fileURL = [dirURL URLByAppendingPathComponent:filename]; 154 | return [fileURL URLByAppendingPathExtension:@"psd"]; 155 | } 156 | 157 | - (void)saveScreenToFile { 158 | NSURL *fileURL = [self psdURLForCurrentDate]; 159 | if (![self.graber saveScreenAsPSDToFileURL:fileURL]) { 160 | NSAlert *alert = [[NSAlert alloc] init]; 161 | alert.messageText = @"An error ocurred"; 162 | [alert addButtonWithTitle:@"OK"]; 163 | alert.informativeText = @"Couldn't grab the screen."; 164 | [alert runModal]; 165 | return; 166 | } 167 | 168 | if ([Preferences shouldAutoOpenFolder]) { 169 | [[NSWorkspace sharedWorkspace] openURL:[self screenshotsDirectoryURL]]; 170 | } 171 | if ([Preferences shouldAutoOpenScreenshot]) { 172 | [[NSWorkspace sharedWorkspace] openURL:fileURL]; 173 | } 174 | } 175 | 176 | #pragma mark Timers 177 | 178 | - (void)updateProgressDegrees:(NSTimer *)timer { 179 | CGFloat scale = [[NSScreen mainScreen] backingScaleFactor]; 180 | NSRect rect = NSMakeRect(0.0, 181 | 0.0, 182 | self.defaultImage.size.width * scale, 183 | self.defaultImage.size.height * scale); 184 | NSPoint center = NSMakePoint(rect.size.width / 2.0 , 185 | rect.size.height / 2.0); 186 | 187 | self.progressImage = [[NSImage alloc] initWithSize:rect.size]; 188 | [self.progressImage lockFocus]; 189 | [[NSColor blackColor] setStroke]; 190 | NSBezierPath *path = [NSBezierPath bezierPath]; 191 | [path appendBezierPathWithArcWithCenter:center 192 | radius:6.5 193 | startAngle:self.progressDegrees 194 | endAngle:self.progressDegrees + 270.0]; 195 | [path setLineWidth:2.0]; 196 | [path stroke]; 197 | [self.progressImage unlockFocus]; 198 | 199 | self.progressDegrees += -10.0; 200 | [self updateBarWithProgress]; 201 | } 202 | 203 | - (void)updateScreenshotTimer:(NSTimer *)timer { 204 | if (self.timerCount != 0) { 205 | [self updateBarWithTimer]; 206 | self.timerCount--; 207 | if ([Preferences shouldPlayTimerSound]) { 208 | [self.timerSound play]; 209 | } 210 | return; 211 | } 212 | 213 | self.timerCount = -1; 214 | [timer invalidate]; 215 | [self grabScreenshot: nil]; 216 | } 217 | 218 | #pragma mark Actions 219 | 220 | - (IBAction)grabScreenshot:(id)sender { 221 | if (self.timerCount != -1) { 222 | return; 223 | } 224 | 225 | NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.04 226 | target:self 227 | selector:@selector(updateProgressDegrees:) 228 | userInfo:nil repeats:YES]; 229 | 230 | if ([Preferences shouldPlayFlashSound]) { 231 | [self.flashSound play]; 232 | } 233 | 234 | int queueId = DISPATCH_QUEUE_PRIORITY_BACKGROUND; 235 | dispatch_async(dispatch_get_global_queue(queueId, 0), ^{ 236 | [self saveScreenToFile]; 237 | dispatch_async(dispatch_get_main_queue(), ^{ 238 | [timer invalidate]; 239 | [self restoreBarWithImage]; 240 | }); 241 | }); 242 | } 243 | 244 | - (IBAction)grabScreenshotWithDelay:(id)sender { 245 | if (self.timerCount != -1) { 246 | return; 247 | } 248 | 249 | self.timerCount = 5; 250 | [self updateBarWithTimer]; 251 | 252 | [NSTimer scheduledTimerWithTimeInterval:1.0 253 | target:self 254 | selector:@selector(updateScreenshotTimer:) 255 | userInfo:nil 256 | repeats:YES]; 257 | } 258 | 259 | - (IBAction)openOutputsFolder:(id)sender { 260 | NSURL *dirURL = [self screenshotsDirectoryURL]; 261 | [[NSWorkspace sharedWorkspace] openURL:dirURL]; 262 | } 263 | 264 | - (IBAction)showWindowsList:(id)sender { 265 | [[ListController sharedController] showWindow:sender]; 266 | } 267 | 268 | - (IBAction)showPreferences:(id)sender { 269 | [[Preferences sharedInstance] showWindow:sender]; 270 | } 271 | 272 | - (IBAction)showPresentation:(id)sender { 273 | [[Presentation sharedInstance] showWindow:sender]; 274 | } 275 | 276 | - (IBAction)contactCustomerSupport:(id)sender { 277 | NSSharingService *service = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeEmail]; 278 | service.recipients = @[SupportAddress]; 279 | service.subject = [NSString stringWithFormat:@"[%@] support", ApplicationName]; 280 | [service performWithItems:@[]]; 281 | } 282 | 283 | - (IBAction)openApplicationWebsite:(id)sender { 284 | NSURL *websiteURL = [NSURL URLWithString:WebsiteStringURL]; 285 | [[NSWorkspace sharedWorkspace] openURL:websiteURL]; 286 | } 287 | 288 | - (IBAction)openAppStorePage:(id)sender { 289 | NSURL *websiteURL = [NSURL URLWithString:AppStoreStringURL]; 290 | [[NSWorkspace sharedWorkspace] openURL:websiteURL]; 291 | } 292 | 293 | - (IBAction)openGitHubPage:(id)sender { 294 | NSURL *websiteURL = [NSURL URLWithString:GitHubStringURL]; 295 | [[NSWorkspace sharedWorkspace] openURL:websiteURL]; 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * const ApplicationName; 12 | extern NSString * const ApplicationID; 13 | extern NSString * const ApplicationHelperID; 14 | 15 | extern NSString * const LaunchCountKey; 16 | extern NSString * const ExportDirectoryDataKey; 17 | extern NSString * const AutoLoginAtStartupKey; 18 | extern NSString * const AutoOpenScreenshotKey; 19 | extern NSString * const AutoOpenFolderKey; 20 | extern NSString * const PlayTimerSoundKey; 21 | extern NSString * const PlayFlashSoundKey; 22 | 23 | extern NSString * const SupportAddress; 24 | extern NSString * const WebsiteStringURL; 25 | extern NSString * const GitHubStringURL; 26 | extern NSString * const AppStoreStringURL; 27 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Constants.m: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "Constants.h" 10 | 11 | NSString * const ApplicationName = @"ScreenToLayers"; 12 | NSString * const ApplicationID = @"com.jeremyvizzini.screentolayers.osx"; 13 | NSString * const ApplicationHelperID = @"com.jeremyvizzini.screentolayers.osx.helper"; 14 | 15 | NSString * const LaunchCountKey = @"LaunchCount"; 16 | NSString * const ExportDirectoryDataKey = @"ExportDirectoryData"; 17 | NSString * const AutoLoginAtStartupKey = @"AutoLoginAtStartup"; 18 | NSString * const AutoOpenScreenshotKey = @"AutoOpenScreenshot"; 19 | NSString * const AutoOpenFolderKey = @"AutoOpenFolder"; 20 | NSString * const PlayTimerSoundKey = @"PlayTimerSound"; 21 | NSString * const PlayFlashSoundKey = @"PlayFlashSound"; 22 | 23 | NSString * const SupportAddress = @"support@screentolayersapp.com"; 24 | NSString * const WebsiteStringURL = @"http://screentolayersapp.com"; 25 | NSString * const GitHubStringURL = @"https://github.com/jeremyvizzini/ScreenToLayers"; 26 | NSString * const AppStoreStringURL = @"https://itunes.apple.com/us/app/screentolayers/id1077317077?ls=1&mt=8"; 27 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/ListController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ListController.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | @import Cocoa; 10 | 11 | @interface ListController : NSWindowController 12 | 13 | #pragma mark Singleton 14 | 15 | + (instancetype)sharedController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/ListController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ListController.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "ListController.h" 10 | #import "ScreenGraber.h" 11 | 12 | static void *ListControllerKVOContext = &ListControllerKVOContext; 13 | 14 | #pragma mark - ListController Private 15 | 16 | @interface ListController () { 17 | IBOutlet NSImageView *outputView; 18 | IBOutlet NSArrayController *arrayController; 19 | } 20 | 21 | @property (strong) ScreenGraber *graber; 22 | @property (weak) IBOutlet NSButton *listOffscreenWindows; 23 | @property (weak) IBOutlet NSButton *listDesktopWindows; 24 | @property (weak) IBOutlet NSButton *imageFramingEffects; 25 | @property (weak) IBOutlet NSButton *imageOpaqueImage; 26 | @property (weak) IBOutlet NSButton *imageShadowsOnly; 27 | @property (weak) IBOutlet NSButton *imageTightFit; 28 | @property (weak) IBOutlet NSMatrix *singleWindow; 29 | 30 | @end 31 | 32 | #pragma mark - ListController Implementation 33 | 34 | @implementation ListController 35 | 36 | #pragma mark Singleton 37 | 38 | + (instancetype)sharedController { 39 | static ListController *controller = nil; 40 | static dispatch_once_t onceToken; 41 | dispatch_once(&onceToken, ^{ 42 | controller = [[self alloc] initWithWindowNibName:@"ListWindow"]; 43 | }); 44 | return controller; 45 | } 46 | 47 | #pragma mark Initializers 48 | 49 | - (void)dealloc { 50 | [arrayController removeObserver:self forKeyPath:@"selectionIndexes"]; 51 | } 52 | 53 | - (void)awakeFromNib { 54 | self.graber = [[ScreenGraber alloc] init]; 55 | self.graber.tightFit = YES; 56 | 57 | [arrayController addObserver:self 58 | forKeyPath:@"selectionIndexes" 59 | options:0 60 | context:&ListControllerKVOContext]; 61 | 62 | 63 | [[self window] makeKeyAndOrderFront:self]; 64 | [self performSelectorOnMainThread:@selector(updateWindowList) 65 | withObject:self 66 | waitUntilDone:NO]; 67 | [self performSelectorOnMainThread:@selector(updateImageWithAllScreen) 68 | withObject:self 69 | waitUntilDone:NO]; 70 | } 71 | 72 | #pragma mark Update data 73 | 74 | - (void)updateWindowList { 75 | [self.graber updateWindowList]; 76 | arrayController.content = self.graber.windowList; 77 | } 78 | 79 | - (void)updateImageWithSelection { 80 | NSImage *image = nil; 81 | NSIndexSet *selection = [arrayController selectionIndexes]; 82 | if([selection count] == 1) { 83 | image = [self.graber screenshotForWindowIndex:selection.firstIndex]; 84 | } else if ([selection count] != 0){ 85 | image = [self.graber screenshotForWindowsSelection:selection]; 86 | } 87 | outputView.image = image; 88 | } 89 | 90 | - (void)updateImageWithAllScreen { 91 | outputView.image = [self.graber screenshot]; 92 | } 93 | 94 | - (void)observeValueForKeyPath:(NSString *)keyPath 95 | ofObject:(id)object 96 | change:(NSDictionary *)change 97 | context:(void *)context 98 | { 99 | if (context == &ListControllerKVOContext) { 100 | [_singleWindow setEnabled:[[arrayController selectedObjects] count] <= 1]; 101 | [self updateImageWithSelection]; 102 | } else { 103 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 104 | } 105 | } 106 | 107 | #pragma mark Actions 108 | 109 | - (IBAction)toggleOffscreenWindows:(id)sender { 110 | self.graber.offscreenWindowsEnabled = ([sender intValue] == NSOnState); 111 | [self updateWindowList]; 112 | [self updateImageWithSelection]; 113 | } 114 | 115 | - (IBAction)toggleDesktopWindows:(id)sender { 116 | self.graber.desktopWindowsEnabled = ([sender intValue] == NSOnState); 117 | [self updateWindowList]; 118 | [self updateImageWithSelection]; 119 | } 120 | 121 | - (IBAction)toggleFramingEffects:(id)sender { 122 | self.graber.framingEffectsEnabled = ([sender intValue] == NSOnState); 123 | [self updateImageWithSelection]; 124 | } 125 | 126 | - (IBAction)toggleOpaqueImage:(id)sender { 127 | self.graber.imageOpaque = ([sender intValue] == NSOnState); 128 | [self updateImageWithSelection]; 129 | } 130 | 131 | - (IBAction)toggleShadowsOnly:(id)sender { 132 | self.graber.shadowsOnly = ([sender intValue] == NSOnState); 133 | [self updateImageWithSelection]; 134 | } 135 | 136 | - (IBAction)toggleTightFit:(id)sender { 137 | self.graber.tightFit = ([sender intValue] == NSOnState); 138 | [self updateImageWithSelection]; 139 | } 140 | 141 | - (IBAction)updateSingleWindowOption:(id)sender { 142 | [self.graber setSingleWindowOptions:[_singleWindow selectedRow]]; 143 | [self updateImageWithSelection]; 144 | } 145 | 146 | - (IBAction)grabScreenShot:(id)sender { 147 | arrayController.selectionIndexes = [[NSIndexSet alloc] init]; 148 | [self updateImageWithAllScreen]; 149 | } 150 | 151 | - (IBAction)refreshWindowList:(id)sender { 152 | [self updateWindowList]; 153 | [self updateImageWithSelection]; 154 | } 155 | 156 | - (IBAction)exportImage:(id)sender { 157 | NSImage *image = outputView.image; 158 | if (!image) { 159 | NSBeep(); 160 | return; 161 | } 162 | 163 | NSSavePanel *panel = [NSSavePanel savePanel]; 164 | [panel setCanCreateDirectories:YES]; 165 | [panel setAllowedFileTypes:@[@"png"]]; 166 | [panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) { 167 | if (result != NSFileHandlingPanelOKButton) { 168 | return; 169 | } 170 | 171 | CGRect imageRect; 172 | CGImageRef imageRef = [image CGImageForProposedRect:&imageRect context:nil hints:nil]; 173 | NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:imageRef]; 174 | NSData *pngData = [imageRep representationUsingType:NSPNGFileType properties:@{}]; 175 | [pngData writeToURL:panel.URL atomically:YES]; 176 | }]; 177 | } 178 | 179 | @end 180 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Preferences.h: -------------------------------------------------------------------------------- 1 | // 2 | // Preferences.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface Preferences : NSWindowController 13 | 14 | #pragma mark Singleton 15 | 16 | + (instancetype)sharedInstance; 17 | 18 | #pragma mark Defaults 19 | 20 | + (BOOL)setupDefaults; 21 | + (BOOL)shouldAutoLoginAtStartup; 22 | + (BOOL)shouldAutoOpenScreenshot; 23 | + (BOOL)shouldAutoOpenFolder; 24 | + (BOOL)shouldPlayTimerSound; 25 | + (BOOL)shouldPlayFlashSound; 26 | + (NSInteger)launchCount; 27 | + (NSURL *)exportDirectoryURL; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Preferences.m: -------------------------------------------------------------------------------- 1 | // 2 | // Preferences.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "Preferences.h" 10 | #import "Constants.h" 11 | 12 | #pragma mark - Preferences Private 13 | 14 | @interface Preferences () 15 | 16 | @property (weak) IBOutlet NSTextField *exportDirectoryLabel; 17 | @property (weak) IBOutlet NSButton *startLoginCheckBox; 18 | 19 | @end 20 | 21 | #pragma mark - Preferences Implementation 22 | 23 | @implementation Preferences 24 | 25 | #pragma mark Singleton 26 | 27 | + (instancetype)sharedInstance { 28 | static Preferences *preferences = nil; 29 | static dispatch_once_t onceToken; 30 | dispatch_once(&onceToken, ^{ 31 | preferences = [[self alloc] initWithWindowNibName:@"Preferences"]; 32 | }); 33 | return preferences; 34 | } 35 | 36 | #pragma mark Initializer 37 | 38 | - (void)awakeFromNib { 39 | [super awakeFromNib]; 40 | [self updateExportDirectoryLabel]; 41 | [self updateStartAtLoginCheckBox]; 42 | } 43 | 44 | #pragma mark Defaults 45 | 46 | + (BOOL)setupDefaults { 47 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 48 | NSInteger count = [ud integerForKey:LaunchCountKey]; 49 | [ud setInteger:(count + 1) forKey:LaunchCountKey]; 50 | 51 | if (count == 0) { 52 | [ud setBool:NO forKey:AutoLoginAtStartupKey]; 53 | [ud setBool:YES forKey:AutoOpenFolderKey]; 54 | [ud setBool:NO forKey:AutoOpenScreenshotKey]; 55 | [ud setBool:YES forKey:PlayTimerSoundKey]; 56 | [ud setBool:YES forKey:PlayFlashSoundKey]; 57 | } 58 | 59 | return [ud synchronize]; 60 | } 61 | 62 | + (BOOL)shouldAutoLoginAtStartup { 63 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 64 | return [ud boolForKey:AutoLoginAtStartupKey]; 65 | } 66 | 67 | + (BOOL)shouldAutoOpenScreenshot { 68 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 69 | return [ud boolForKey:AutoOpenScreenshotKey]; 70 | } 71 | 72 | + (BOOL)shouldAutoOpenFolder { 73 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 74 | return [ud boolForKey:AutoOpenFolderKey]; 75 | } 76 | 77 | + (BOOL)shouldPlayTimerSound { 78 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 79 | return [ud boolForKey:PlayTimerSoundKey]; 80 | } 81 | 82 | + (BOOL)shouldPlayFlashSound { 83 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 84 | return [ud boolForKey:PlayFlashSoundKey]; 85 | } 86 | 87 | + (NSInteger)launchCount { 88 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 89 | return [ud integerForKey:LaunchCountKey]; 90 | } 91 | 92 | #pragma mark Export URL 93 | 94 | static BOOL _isDefaultExportDirectory; 95 | static NSURL *_exportDirectoryURL; 96 | 97 | + (NSURL *)restoreDefaultExportDirectoryURL { 98 | NSSearchPathDirectory dir = NSPicturesDirectory; 99 | NSSearchPathDomainMask mask = NSUserDomainMask; 100 | NSArray *allPaths = NSSearchPathForDirectoriesInDomains(dir, mask, YES); 101 | NSString *path = [allPaths firstObject]; 102 | path = [path stringByAppendingPathComponent:ApplicationName]; 103 | 104 | _exportDirectoryURL = [[NSURL alloc] initFileURLWithPath:path]; 105 | _isDefaultExportDirectory = YES; 106 | 107 | 108 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 109 | [ud setObject: nil forKey:ExportDirectoryDataKey]; 110 | 111 | return _exportDirectoryURL; 112 | } 113 | 114 | + (void)setExportDirectoryURL:(NSURL *)URL { 115 | if (_exportDirectoryURL && !_isDefaultExportDirectory) { 116 | [_exportDirectoryURL stopAccessingSecurityScopedResource]; 117 | _exportDirectoryURL = nil; 118 | } 119 | 120 | _exportDirectoryURL = URL; 121 | _isDefaultExportDirectory = NO; 122 | 123 | NSError *error; 124 | NSData *data = [URL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope 125 | includingResourceValuesForKeys:nil 126 | relativeToURL:nil 127 | error:&error]; 128 | 129 | if (error || !URL.startAccessingSecurityScopedResource) { 130 | [Preferences showRestoreExportDirectoryAlert]; 131 | [Preferences restoreDefaultExportDirectoryURL]; 132 | } 133 | 134 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 135 | [ud setObject:data forKey:ExportDirectoryDataKey]; 136 | [ud synchronize]; 137 | } 138 | 139 | + (NSURL *)exportDirectoryURL { 140 | if (_exportDirectoryURL) { 141 | return _exportDirectoryURL; 142 | } 143 | 144 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 145 | NSData *data = [ud dataForKey:ExportDirectoryDataKey]; 146 | if (!data) { 147 | return [self restoreDefaultExportDirectoryURL]; 148 | } 149 | 150 | BOOL isStale; 151 | NSError *error; 152 | _isDefaultExportDirectory = NO; 153 | NSURLBookmarkFileCreationOptions opt; 154 | opt = NSURLBookmarkResolutionWithSecurityScope; 155 | _exportDirectoryURL = [NSURL URLByResolvingBookmarkData:data 156 | options:opt 157 | relativeToURL:nil 158 | bookmarkDataIsStale:&isStale 159 | error:&error]; 160 | 161 | if (error || isStale) { 162 | [Preferences showRestoreExportDirectoryAlert]; 163 | [Preferences restoreDefaultExportDirectoryURL]; 164 | return _exportDirectoryURL; 165 | } 166 | 167 | [_exportDirectoryURL startAccessingSecurityScopedResource]; 168 | return _exportDirectoryURL; 169 | } 170 | 171 | #pragma mark UI 172 | 173 | - (void)updateExportDirectoryLabel { 174 | NSString *path = [Preferences exportDirectoryURL].path; 175 | path = [path stringByAbbreviatingWithTildeInPath]; 176 | self.exportDirectoryLabel.stringValue = path; 177 | } 178 | 179 | - (void)updateStartAtLoginCheckBox { 180 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 181 | BOOL state = [ud boolForKey:AutoLoginAtStartupKey]; 182 | self.startLoginCheckBox.state = state ? NSOnState : NSOffState; 183 | } 184 | 185 | + (void)showRestoreExportDirectoryAlert { 186 | NSAlert *alert = [[NSAlert alloc] init]; 187 | alert.messageText = @"An error ocurred"; 188 | alert.informativeText = @"The app will restore the default export directory."; 189 | [alert addButtonWithTitle:@"OK"]; 190 | [alert runModal]; 191 | } 192 | 193 | + (void)showLaunchAtStartupAlert:(BOOL)state { 194 | NSAlert *alert = [[NSAlert alloc] init]; 195 | alert.messageText = @"An error ocurred"; 196 | [alert addButtonWithTitle:@"OK"]; 197 | alert.informativeText = [NSString stringWithFormat: 198 | @"Couldn't %@ %@ from login item list.", 199 | state ? @"add" : @"remove", 200 | ApplicationName]; 201 | [alert runModal]; 202 | } 203 | 204 | #pragma mark Actions 205 | 206 | - (IBAction)toogleLaunchAtStartup:(id)sender { 207 | NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 208 | BOOL state = ![ud boolForKey:AutoLoginAtStartupKey]; 209 | CFStringRef identifier = (__bridge CFStringRef)ApplicationHelperID; 210 | Boolean res = SMLoginItemSetEnabled(identifier, state); 211 | 212 | if (res) { 213 | [ud setBool:state forKey:AutoLoginAtStartupKey]; 214 | [ud synchronize]; 215 | } else { 216 | [Preferences showLaunchAtStartupAlert:state]; 217 | } 218 | 219 | [self updateStartAtLoginCheckBox]; 220 | } 221 | 222 | - (IBAction)chooseExportDirectory:(id)sender { 223 | NSOpenPanel* panel = [NSOpenPanel openPanel]; 224 | panel.canChooseDirectories = YES; 225 | panel.canCreateDirectories = YES; 226 | panel.canChooseFiles = NO; 227 | panel.allowsMultipleSelection = NO; 228 | 229 | [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { 230 | if (result != NSFileHandlingPanelOKButton) { 231 | return; 232 | } 233 | [Preferences setExportDirectoryURL:panel.URL]; 234 | [self updateExportDirectoryLabel]; 235 | }]; 236 | } 237 | 238 | - (IBAction)resetExportDirectory:(id)sender { 239 | [Preferences restoreDefaultExportDirectoryURL]; 240 | [self updateExportDirectoryLabel]; 241 | } 242 | 243 | @end 244 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Presentation.h: -------------------------------------------------------------------------------- 1 | // 2 | // Presentation.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface Presentation : NSWindowController 13 | 14 | #pragma mark Singleton 15 | 16 | + (instancetype)sharedInstance; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/Presentation.m: -------------------------------------------------------------------------------- 1 | // 2 | // Presentation.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "Presentation.h" 10 | #import "Constants.h" 11 | 12 | 13 | #pragma mark - Presentation Private 14 | 15 | @interface Presentation () 16 | 17 | @end 18 | 19 | #pragma mark - Presentation Implementation 20 | 21 | @implementation Presentation 22 | 23 | #pragma mark Singleton 24 | 25 | + (instancetype)sharedInstance { 26 | static Presentation *presentation = nil; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | presentation = [[self alloc] initWithWindowNibName:@"Presentation"]; 30 | }); 31 | return presentation; 32 | } 33 | 34 | #pragma mark Initializer 35 | 36 | - (void)awakeFromNib { 37 | [super awakeFromNib]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/ScreenGraber.h: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenGraber.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | @import Cocoa; 10 | 11 | extern NSString * const AppNameKey; 12 | extern NSString * const WindowOriginKey; 13 | extern NSString * const WindowSizeKey; 14 | extern NSString * const WindowIDKey; 15 | extern NSString * const WindowLevelKey; 16 | extern NSString * const WindowOrderKey; 17 | 18 | typedef NS_ENUM(NSUInteger, SingleWindowOptions) { 19 | SingleWindowOptionsAboveOnly = 0, 20 | SingleWindowOptionsAboveIncluded = 1, 21 | SingleWindowOptionsOnly = 2, 22 | SingleWindowOptionsBelowIncluded = 3, 23 | SingleWindowOptionsBelowOnly = 4 24 | }; 25 | 26 | @interface ScreenGraber : NSObject 27 | 28 | #pragma mark Windows list 29 | 30 | - (void)updateWindowList; 31 | - (NSString *)nameOfWindowAtIndex:(NSInteger)index; 32 | @property (readonly, strong, nonatomic) NSArray *windowList; 33 | 34 | #pragma mark Grab screenshots 35 | 36 | - (CGImageRef)newScreenshot; 37 | - (CGImageRef)newScreenshotForWindowIndex:(NSInteger)index; 38 | - (CGImageRef)newScreenshotForWindowsSelection:(NSIndexSet *)selection; 39 | 40 | - (NSImage *)screenshot; 41 | - (NSImage *)screenshotForWindowIndex:(NSInteger)index; 42 | - (NSImage *)screenshotForWindowsSelection:(NSIndexSet *)selection; 43 | 44 | #pragma mark Save screen 45 | 46 | - (BOOL)saveScreenAsPSDToFileURL:(NSURL *)fileURL; 47 | 48 | #pragma mark Settings 49 | 50 | @property (nonatomic, getter=isTightFit) BOOL tightFit; 51 | @property (nonatomic, getter=isImageOpaque) BOOL imageOpaque; 52 | @property (nonatomic, getter=isShadowsOnly) BOOL shadowsOnly; 53 | @property (nonatomic, getter=isCursorOnTop) BOOL cursorOnTop; 54 | @property (nonatomic, getter=isDesktopWindowsEnabled) BOOL desktopWindowsEnabled; 55 | @property (nonatomic, getter=isFramingEffectsEnabled) BOOL framingEffectsEnabled; 56 | @property (nonatomic, getter=isOffscreenWindowsEnabled) BOOL offscreenWindowsEnabled; 57 | - (void)setSingleWindowOptions:(SingleWindowOptions)windowOptions; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/ScreenGraber.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenGraber.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "ScreenGraber.h" 10 | #import "PSDWriter.h" 11 | 12 | NSString * const AppNameKey = @"applicationName"; 13 | NSString * const WindowOriginKey = @"windowOrigin"; 14 | NSString * const WindowSizeKey = @"windowSize"; 15 | NSString * const WindowIDKey = @"windowID"; 16 | NSString * const WindowLevelKey = @"windowLevel"; 17 | NSString * const WindowOrderKey = @"windowOrder"; 18 | 19 | #pragma mark - Helpers 20 | 21 | static inline 22 | void ChangeBits(uint32_t *currentBits, uint32_t flagsToChange, BOOL setFlags) { 23 | if(setFlags) { 24 | *currentBits = *currentBits | flagsToChange; 25 | } else { 26 | *currentBits = *currentBits & ~flagsToChange; 27 | } 28 | } 29 | 30 | #pragma mark - ScreenGraber Private 31 | 32 | @interface ScreenGraber () 33 | 34 | @property (assign) CGRect imageBounds; 35 | @property (assign) CGWindowListOption listOptions; 36 | @property (assign) CGWindowListOption windowOptions; 37 | @property (assign) CGWindowImageOption imageOptions; 38 | @property (strong) NSMutableArray *prunedWindowList; 39 | 40 | @end 41 | 42 | #pragma mark - ScreenGraber Implementation 43 | 44 | @implementation ScreenGraber 45 | 46 | - (instancetype)init { 47 | self = [super init]; 48 | if (self) { 49 | self.imageBounds = CGRectInfinite; 50 | self.listOptions = kCGWindowListOptionOnScreenOnly; 51 | self.imageOptions = 0; 52 | self.windowOptions = kCGWindowListOptionIncludingWindow; 53 | self.prunedWindowList = [NSMutableArray array]; 54 | } 55 | return self; 56 | } 57 | 58 | #pragma mark Image generation 59 | 60 | static 61 | void WindowListApplierFunction(const void *inputDictionary, void *context) 62 | { 63 | NSDictionary *entry = (__bridge NSDictionary*)inputDictionary; 64 | ScreenGraber *grabber = (__bridge ScreenGraber *)context; 65 | int sharingState = [entry[(id)kCGWindowSharingState] intValue]; 66 | if (sharingState == kCGWindowSharingNone) { 67 | return; 68 | } 69 | 70 | NSMutableDictionary *outputEntry = [NSMutableDictionary dictionary]; 71 | outputEntry[AppNameKey] = [NSString stringWithFormat:@"%@ (%@)", 72 | entry[(id)kCGWindowOwnerName] ?: @"((unknwown))", 73 | entry[(id)kCGWindowOwnerPID]];; 74 | 75 | CGRect bounds; 76 | CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)entry[(id)kCGWindowBounds], &bounds); 77 | outputEntry[WindowOriginKey] = [NSString stringWithFormat:@"%.0f/%.0f", 78 | bounds.origin.x, 79 | bounds.origin.y]; 80 | outputEntry[WindowSizeKey] = [NSString stringWithFormat:@"%.0f*%.0f", 81 | bounds.size.width, 82 | bounds.size.height]; 83 | 84 | outputEntry[WindowIDKey] = entry[(id)kCGWindowNumber]; 85 | outputEntry[WindowLevelKey] = entry[(id)kCGWindowLayer]; 86 | outputEntry[WindowOrderKey] = @(grabber.prunedWindowList.count); 87 | 88 | [grabber.prunedWindowList addObject:outputEntry]; 89 | } 90 | 91 | - (CFArrayRef)newWindowListFromSelectedObjects:(NSArray *)selectedObjects { 92 | NSArray *sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:WindowOrderKey ascending:YES]]; 93 | NSArray *sortedSelection = [selectedObjects sortedArrayUsingDescriptors:sortDescriptors]; 94 | 95 | NSInteger i = 0, count = [sortedSelection count]; 96 | const void *windowIDs[count]; 97 | for (NSMutableDictionary *entry in sortedSelection) { 98 | windowIDs[i++] = (void *)[entry[WindowIDKey] unsignedIntegerValue]; 99 | } 100 | 101 | CFArrayRef windowIDsArray = CFArrayCreate(kCFAllocatorDefault, 102 | (const void **)windowIDs, 103 | [sortedSelection count], 104 | NULL); 105 | return windowIDsArray; 106 | } 107 | 108 | #pragma mark Windows list 109 | 110 | - (void)updateWindowList { 111 | CFArrayRef windowList = CGWindowListCopyWindowInfo(self.listOptions, kCGNullWindowID); 112 | [self.prunedWindowList removeAllObjects]; 113 | CFArrayApplyFunction(windowList, 114 | CFRangeMake(0, CFArrayGetCount(windowList)), 115 | &WindowListApplierFunction, 116 | (__bridge void *)(self)); 117 | CFRelease(windowList); 118 | } 119 | 120 | - (NSString *)nameOfWindowAtIndex:(NSInteger)index { 121 | return self.prunedWindowList[index][AppNameKey]; 122 | } 123 | 124 | - (NSArray *)windowList { 125 | return self.prunedWindowList; 126 | } 127 | 128 | #pragma mark Grab screenshot 129 | 130 | - (CGImageRef)newScreenshot { 131 | CGImageRef imageRef = CGWindowListCreateImage(CGRectInfinite, 132 | kCGWindowListOptionOnScreenOnly, 133 | kCGNullWindowID, 134 | kCGWindowImageDefault); 135 | return imageRef; 136 | } 137 | 138 | - (CGImageRef)newScreenshotForWindowIndex:(NSInteger)index { 139 | NSDictionary *windowDict = self.prunedWindowList[index]; 140 | CGWindowID windowID = (CGWindowID)[windowDict[WindowIDKey] unsignedIntegerValue]; 141 | CGImageRef imageRef = CGWindowListCreateImage(self.imageBounds, 142 | self.windowOptions, 143 | windowID, 144 | self.imageOptions); 145 | return imageRef; 146 | } 147 | 148 | - (CGImageRef)newScreenshotForWindowsSelection:(NSIndexSet *)selection { 149 | NSArray *objects = [self.prunedWindowList objectsAtIndexes:selection]; 150 | CFArrayRef windowIDs = [self newWindowListFromSelectedObjects:objects]; 151 | CGImageRef imageRef = CGWindowListCreateImageFromArray(self.imageBounds, 152 | windowIDs, 153 | self.imageOptions); 154 | CFRelease(windowIDs); 155 | return imageRef; 156 | } 157 | 158 | - (NSImage *)screenshot { 159 | CGImageRef imageRef = [self newScreenshot]; 160 | NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSZeroSize]; 161 | CGImageRelease(imageRef); 162 | return image; 163 | } 164 | 165 | - (NSImage *)screenshotForWindowIndex:(NSInteger)index { 166 | CGImageRef imageRef = [self newScreenshotForWindowIndex:index]; 167 | NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSZeroSize]; 168 | CGImageRelease(imageRef); 169 | return image; 170 | } 171 | 172 | - (NSImage *)screenshotForWindowsSelection:(NSIndexSet *)selection { 173 | CGImageRef imageRef = [self newScreenshotForWindowsSelection:selection]; 174 | NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSZeroSize]; 175 | CGImageRelease(imageRef); 176 | return image; 177 | } 178 | 179 | #pragma mark Save screen 180 | 181 | - (BOOL)saveScreenAsPSDToFileURL:(NSURL *)fileURL { 182 | CGFloat scaleFactor = [[NSScreen mainScreen] backingScaleFactor]; 183 | NSRect frame = [[NSScreen mainScreen] frame]; 184 | frame.size.width *= scaleFactor; 185 | frame.size.height *= scaleFactor; 186 | 187 | [self updateWindowList]; 188 | PSDWriter *writer = [[PSDWriter alloc] initWithDocumentSize:frame.size]; 189 | 190 | CGImageRef imageRef = [self newScreenshot]; 191 | writer.flattenedData = CGImageGetData(imageRef); 192 | CGImageRelease(imageRef); 193 | 194 | 195 | for (NSInteger i = self.windowList.count - 1; i >= 0; i--) { 196 | NSString *name = [self nameOfWindowAtIndex:i]; 197 | imageRef = [self newScreenshotForWindowIndex:i]; 198 | [writer addLayerWithCGImage:imageRef andName:name andOpacity:1.0 andOffset:CGPointZero]; 199 | CGImageRelease(imageRef); 200 | } 201 | 202 | if (self.cursorOnTop) { 203 | CGPoint offset = [NSEvent mouseLocation]; 204 | offset = CGPointMake(offset.x * scaleFactor, offset.y * scaleFactor); 205 | offset.y = [NSScreen mainScreen].frame.size.height * scaleFactor - offset.y; 206 | NSImage *image = [NSCursor currentCursor].image; 207 | CGImageRef imageRef = [image CGImageForProposedRect:NULL context:nil hints:nil]; 208 | [writer addLayerWithCGImage:imageRef andName:@"Cursor" andOpacity:1.0 andOffset:offset]; 209 | } 210 | 211 | NSData *psdData = [writer createPSDData]; 212 | if (!psdData) { 213 | NSLog(@"Cannot create PSD file from screen."); 214 | return NO; 215 | } 216 | if (![psdData writeToURL:fileURL atomically:YES]) { 217 | NSLog(@"Cannot write PSD file at URL %@", fileURL); 218 | return NO; 219 | } 220 | 221 | return YES; 222 | } 223 | 224 | #pragma mark Settings 225 | 226 | - (void)setOffscreenWindowsEnabled:(BOOL)flag { 227 | ChangeBits(&_listOptions, kCGWindowListOptionOnScreenOnly, !flag); 228 | } 229 | 230 | - (BOOL)isOffscreenWindowsEnabled { 231 | return !(_listOptions & kCGWindowListOptionOnScreenOnly); 232 | } 233 | 234 | - (void)setDesktopWindowsEnabled:(BOOL)flag { 235 | ChangeBits(&_listOptions, kCGWindowListExcludeDesktopElements, !flag); 236 | } 237 | 238 | - (BOOL)isDesktopWindowsEnabled { 239 | return !(_listOptions & kCGWindowListExcludeDesktopElements); 240 | } 241 | 242 | - (void)setFramingEffectsEnabled:(BOOL)flag { 243 | ChangeBits(&_imageOptions, kCGWindowImageBoundsIgnoreFraming, flag); 244 | } 245 | 246 | - (BOOL)isFramingEffectsEnabled { 247 | return (_imageOptions & kCGWindowImageBoundsIgnoreFraming); 248 | } 249 | 250 | - (void)setImageOpaque:(BOOL)flag { 251 | ChangeBits(&_imageOptions, kCGWindowImageShouldBeOpaque, flag); 252 | } 253 | 254 | - (BOOL)isImageOpaque { 255 | return (_imageOptions & kCGWindowImageShouldBeOpaque); 256 | } 257 | 258 | - (void)setShadowsOnly:(BOOL)flag { 259 | ChangeBits(&_imageOptions, kCGWindowImageOnlyShadows, flag); 260 | } 261 | 262 | - (BOOL)isShadowsOnly { 263 | return (_imageOptions & kCGWindowImageOnlyShadows); 264 | } 265 | 266 | - (void)setTightFit:(BOOL)flag { 267 | _imageBounds = (flag) ? CGRectNull : CGRectInfinite; 268 | } 269 | 270 | - (BOOL)isTightFit { 271 | return CGRectIsNull(_imageBounds); 272 | } 273 | 274 | - (void)setSingleWindowOptions:(SingleWindowOptions)windowOptions { 275 | CGWindowListOption options = 0; 276 | switch(windowOptions) { 277 | case SingleWindowOptionsAboveOnly: 278 | options = kCGWindowListOptionOnScreenAboveWindow; 279 | break; 280 | case SingleWindowOptionsAboveIncluded: 281 | options = kCGWindowListOptionOnScreenAboveWindow | kCGWindowListOptionIncludingWindow; 282 | break; 283 | case SingleWindowOptionsOnly: 284 | options = kCGWindowListOptionIncludingWindow; 285 | break; 286 | case SingleWindowOptionsBelowIncluded: 287 | options = kCGWindowListOptionOnScreenBelowWindow | kCGWindowListOptionIncludingWindow; 288 | break; 289 | case SingleWindowOptionsBelowOnly: 290 | options = kCGWindowListOptionOnScreenBelowWindow; 291 | break; 292 | default: 293 | break; 294 | } 295 | self.windowOptions = options; 296 | } 297 | 298 | @end 299 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/WhiteView.h: -------------------------------------------------------------------------------- 1 | // 2 | // WhiteView.h 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | 11 | @interface WhiteView : NSView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/Application/WhiteView.m: -------------------------------------------------------------------------------- 1 | // 2 | // WhiteView.m 3 | // ScreenToLayers 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "WhiteView.h" 10 | 11 | @implementation WhiteView 12 | 13 | - (void)drawRect:(NSRect)dirtyRect { 14 | [[NSColor whiteColor] setFill]; 15 | NSRectFill(self.bounds); 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/NSDataPSDAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDataPSDAdditions.h 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSMutableData (PSDAdditions) 13 | 14 | /** Allows you to append a numeric value to an NSMutableData object and pad it to any length. 15 | 16 | For example, we could say [data appendValue: 2 withLength: 5], and 00002 would be written 17 | into the data object. Very useful for writing to file formats that have header structures 18 | that require a certain number of bytes be used for a certain value. i.e. PSD and TIFF 19 | 20 | @param value: The value to append 21 | @param length: The number of bytes that should be used to store the value. The value will be padded 22 | to length bytes regardless of the number of bytes required to store it. 23 | */ 24 | - (void)appendValue:(long)value withLength:(int)length; 25 | 26 | @end 27 | 28 | @interface NSData (PSDAdditions) 29 | 30 | /** Takes packedBits data and prints out a description of the packed contents by 31 | running the decode operation and explaining via NSLog how the data is being 32 | decoded. Useful for checking that packedBits data is correct. */ 33 | - (NSString *)packedBitsDescription; 34 | 35 | /** A special version of packedBits which will take the data and pack every nth 36 | value. 37 | 38 | This is important for PSDWriter because it's necessary to encode R, then G, 39 | then B, then A data - so we essentially start at offset 0, skip 4, then do offset 1, 40 | skip 4, etc... to compress the data with very minimal memory footprint. 41 | 42 | For normal packbits just to skip = 1 43 | 44 | @param range: The range within the data object that should be encoded. Useful 45 | for specifying a non-zero starting offset to get a certain channel encoded. 46 | @param skip: The number of bytes to advance as the data is encoded. Skip = 1 will 47 | encode every byte, skip = 4 will encode every fourth byte, and so on. 48 | */ 49 | - (NSData *)packedBitsForRange:(NSRange)range skip:(int)skip; 50 | 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/NSDataPSDAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDataPSDAdditions.m 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "NSDataPSDAdditions.h" 10 | 11 | #define MIN_RUN 3 /* minimum run length to encode */ 12 | #define MAX_RUN 127 /* maximum run length to encode */ 13 | #define MAX_COPY 128 /* maximum characters to copy */ 14 | 15 | /* maximum that can be read before copy block is written */ 16 | #define MAX_READ (MAX_COPY + MIN_RUN - 1) 17 | 18 | 19 | @implementation NSMutableData (PSDAdditions) 20 | 21 | - (void)appendValue:(long)value withLength:(int)length 22 | { 23 | Byte bytes[8]; 24 | 25 | double divider = 1; 26 | for (int ii = 0; ii < length; ii++){ 27 | bytes[length-ii-1] = (long)(value / divider) % 256; 28 | divider *= 256; 29 | } 30 | 31 | [self appendBytes:&bytes length:length]; 32 | } 33 | 34 | @end 35 | 36 | @implementation NSData (PSDAdditions) 37 | 38 | - (NSString*)packedBitsDescription 39 | { 40 | NSMutableString * description = [NSMutableString string]; 41 | char * row = (char*)[self bytes]; 42 | int pbOffset = 0; 43 | int pbResultBytes = 0; 44 | 45 | while (pbOffset < [self length]){ 46 | int headerByte = (int)row[pbOffset]; 47 | if (headerByte < 0){ 48 | int repeatTimes = 1-headerByte; 49 | UInt8 repeatByte = (UInt8)row[pbOffset+1]; 50 | [description appendFormat: @"Printing %u %d times. ", repeatByte, repeatTimes]; 51 | 52 | pbResultBytes += repeatTimes; 53 | pbOffset += 2; 54 | } else if (headerByte >= 0){ 55 | [description appendFormat: @"Printing %d literal bytes. ", headerByte + 1]; 56 | pbResultBytes += headerByte + 1; 57 | pbOffset += 2 + headerByte; 58 | } 59 | } 60 | 61 | [description appendFormat: @"Total: %d bytes decoded.", pbResultBytes]; 62 | return description; 63 | } 64 | 65 | - (NSData*)packedBitsForRange:(NSRange)range skip:(int)skip 66 | { 67 | const char * bytesIn = [self bytes]; 68 | unsigned long bytesLength = range.location + range.length; 69 | unsigned long bytesOffset = range.location; 70 | NSMutableData * dataOut = [NSMutableData data]; 71 | 72 | BOOL currIsEOF = NO; 73 | unsigned char currChar; /* current character */ 74 | unsigned char charBuf[MAX_READ]; /* buffer of already read characters */ 75 | int count; /* number of characters in a run */ 76 | 77 | /* prime the read loop */ 78 | currChar = bytesIn[bytesOffset]; 79 | bytesOffset = bytesOffset + skip; 80 | count = 0; 81 | 82 | /* read input until there's nothing left */ 83 | while (!currIsEOF) 84 | { 85 | charBuf[count] = (unsigned char)currChar; 86 | count++; 87 | 88 | if (count >= MIN_RUN) { 89 | int i; 90 | /* check for run charBuf[count - 1] .. charBuf[count - MIN_RUN]*/ 91 | for (i = 2; i <= MIN_RUN; i++){ 92 | if (currChar != charBuf[count - i]){ 93 | /* no run */ 94 | i = 0; 95 | break; 96 | } 97 | } 98 | 99 | if (i != 0) 100 | { 101 | /* we have a run write out buffer before run*/ 102 | int nextChar; 103 | 104 | if (count > MIN_RUN){ 105 | /* block size - 1 followed by contents */ 106 | UInt8 a = count - MIN_RUN - 1; 107 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 108 | [dataOut appendBytes:&charBuf length:sizeof(unsigned char) * (count - MIN_RUN)]; 109 | } 110 | 111 | /* determine run length (MIN_RUN so far) */ 112 | count = MIN_RUN; 113 | while (true) { 114 | if (bytesOffset < bytesLength){ 115 | nextChar = bytesIn[bytesOffset]; 116 | bytesOffset += skip; 117 | } else { 118 | currIsEOF = YES; 119 | nextChar = EOF; 120 | } 121 | if (nextChar != currChar) break; 122 | 123 | count++; 124 | if (count == MAX_RUN){ 125 | /* run is at max length */ 126 | break; 127 | } 128 | } 129 | 130 | /* write out encoded run length and run symbol */ 131 | UInt8 a = ((int)(1 - (int)(count))); 132 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 133 | [dataOut appendBytes:&currChar length:sizeof(UInt8)]; 134 | 135 | if ((!currIsEOF) && (count != MAX_RUN)){ 136 | /* make run breaker start of next buffer */ 137 | charBuf[0] = nextChar; 138 | count = 1; 139 | } else { 140 | /* file or max run ends in a run */ 141 | count = 0; 142 | } 143 | } 144 | } 145 | 146 | if (count == MAX_READ) 147 | { 148 | int i; 149 | 150 | /* write out buffer */ 151 | UInt8 a = MAX_COPY - 1; 152 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 153 | [dataOut appendBytes:&charBuf[0] length:sizeof(unsigned char) * MAX_COPY]; 154 | 155 | /* start a new buffer */ 156 | count = MAX_READ - MAX_COPY; 157 | 158 | /* copy excess to front of buffer */ 159 | for (i = 0; i < count; i++) 160 | charBuf[i] = charBuf[MAX_COPY + i]; 161 | } 162 | 163 | if (bytesOffset < bytesLength) 164 | currChar = bytesIn[bytesOffset]; 165 | else 166 | currIsEOF = YES; 167 | bytesOffset += skip; 168 | } 169 | 170 | /* write out last buffer */ 171 | if (0 != count) 172 | { 173 | if (count <= MAX_COPY) { 174 | /* write out entire copy buffer */ 175 | UInt8 a = count - 1; 176 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 177 | [dataOut appendBytes:&charBuf length:sizeof(unsigned char) * count]; 178 | } 179 | else 180 | { 181 | /* we read more than the maximum for a single copy buffer */ 182 | UInt8 a = MAX_COPY - 1; 183 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 184 | [dataOut appendBytes:&charBuf length:sizeof(unsigned char) * MAX_COPY]; 185 | 186 | /* write out remainder */ 187 | count -= MAX_COPY; 188 | a = count - 1; 189 | [dataOut appendBytes:&a length:sizeof(UInt8)]; 190 | [dataOut appendBytes:&charBuf[MAX_COPY] length:sizeof(unsigned char) * count]; 191 | } 192 | } 193 | 194 | return dataOut; 195 | } 196 | 197 | 198 | 199 | @end 200 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/PSDLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSDLayer.h 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | 11 | @interface PSDLayer : NSObject 12 | 13 | /** The name of the layer. I believe this must be 16 characters or less. */ 14 | 15 | @property (nonatomic, strong) NSString * name; 16 | /** The image data in RGBA or RGB format, depending on whether the PSDWriter.layerChannelCount 17 | is set to 4 or 3, respectively.*/ 18 | @property (nonatomic, strong) NSData * imageData; 19 | 20 | /** The opacity of the layer between 0 and 1. */ 21 | @property (nonatomic, assign) float opacity; 22 | 23 | /** The rectangle the layer should be placed within in the PSD. Note that scaling is not currently 24 | supported, so you should really only adjust the origin of this rect to move the imageData around 25 | within the PSD. 26 | */ 27 | @property (nonatomic, assign) CGRect rect; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/PSDLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSDLayer.m 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "PSDLayer.h" 10 | 11 | @implementation PSDLayer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/PSDWriter.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSDWriter.h 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | #if TARGET_OS_IPHONE 11 | #import 12 | #endif 13 | 14 | @interface PSDWriter : NSObject 15 | { 16 | CGSize documentSize; 17 | NSMutableArray * layers; 18 | int layerChannelCount; 19 | 20 | NSData * flattenedData; 21 | CGContextRef flattenedContext; 22 | 23 | BOOL shouldFlipLayerData; 24 | BOOL shouldUnpremultiplyLayerData; 25 | } 26 | 27 | /** The PSDLayer objects with layer data, names, etc... Note that when you call 28 | createPSDData, this array is slowly emptied - the PSDWriter removes the individual layers 29 | from memory as it builds the PSD file. */ 30 | @property (nonatomic, strong) NSMutableArray *layers; 31 | 32 | /** The size of the PSD you're exporting. */ 33 | @property (nonatomic, assign) CGSize documentSize; 34 | 35 | /** The number of channels in each layer. Defaults to 4, unless layers 36 | are not transparent. At the moment, this setting applies to all layers.*/ 37 | @property (nonatomic, assign) int layerChannelCount; 38 | 39 | /** Optional. The RGBA data for a flattened "preview" of the PSD. */ 40 | @property (nonatomic, strong) NSData * flattenedData; 41 | 42 | /** Allows you to automatically vertically flip the image data when it's being 43 | written to PSD. This is important if the source images are coming from OpenGL or 44 | another drawing system with an inverted coordinate system.*/ 45 | @property (nonatomic, assign) BOOL shouldFlipLayerData; 46 | 47 | /** Allows you to automatically unpremultiply the image data. Premultiplication is 48 | a process by which the R,G, and B values are multiplied by the alpha. Setting this 49 | to YES will cause RGB to be divided by A. You'll know you need to do this if the 50 | image comes out darker than you expect. */ 51 | @property (nonatomic, assign) BOOL shouldUnpremultiplyLayerData; 52 | 53 | /** Initializes a new PSDWriter for creating a PSD document with the specified size. 54 | @param s The document size*/ 55 | - (id)initWithDocumentSize:(CGSize)s; 56 | 57 | /** Adds a new layer to the PSD image with the provided properties. 58 | 59 | If you are using NSImages and not CGImages, use the following code to convert to CGImageRefs: 60 | 61 | NSImage* yourImage; 62 | CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)[yourImage TIFFRepresentation], NULL); 63 | CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL); 64 | 65 | If you prefer, you can setup PSDLayers by yourself 66 | and put them in the PSDWriter.layers array, but this method automatically creates the flattenedData, 67 | an image that is a flattened preview of the layered PSD. If you populate the layer objects yourself, 68 | you need to provide the flattened image data yourself. 69 | 70 | Note: Having layers partially off the edge of the canvas is not currently supported. 71 | 72 | @param image The image to be added. Does not need to be the same size as the document, but it cannot be larger. 73 | @param name The name you'd like to give the layer. 74 | @param opacity The opacity of the layer, from [0-1] 75 | @param offset The offset of the layer within the document. Use this to position layers within the PSD. 76 | */ 77 | - (void)addLayerWithCGImage:(CGImageRef)image 78 | andName:(NSString*)name 79 | andOpacity:(float)opacity 80 | andOffset:(CGPoint)offset; 81 | 82 | /* Generates an NSData object representing a PSD image with the width and height specified by documentSize 83 | and the contents specified by the layers array. Note that this function can be (and really should be) 84 | called on a separate thread. 85 | 86 | @return PSD data. Write this data to a file or attach it to an email, etc... 87 | 88 | Note: You cannot call this function multiple times. After calling createPSDData and getting the document data, 89 | you should discard the PSDWriter object. This function is destructive and deletes the information you provided 90 | in the layers array to conserve memory as it writes the PSD data. 91 | */ 92 | - (NSData *)createPSDData; 93 | 94 | @end 95 | 96 | /** A convenience function for getting RGBA NSData from a CGImageRef. */ 97 | NSData *CGImageGetData(CGImageRef image); 98 | NSData *CGImageGetDataForRegion(CGImageRef image, CGRect region); 99 | -------------------------------------------------------------------------------- /ScreenToLayers/Sources/PSD writer/PSDWriter.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSDWriter.m 3 | // ScreenToLayers 4 | // 5 | // Forked from : https://github.com/bengotow/PSDWriter 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "PSDWriter.h" 10 | #import "NSDataPSDAdditions.h" 11 | #import "PSDLayer.h" 12 | 13 | @implementation PSDWriter 14 | 15 | @synthesize documentSize; 16 | @synthesize layers; 17 | @synthesize layerChannelCount; 18 | @synthesize flattenedData; 19 | 20 | @synthesize shouldFlipLayerData; 21 | @synthesize shouldUnpremultiplyLayerData; 22 | 23 | - (id)init 24 | { 25 | self = [super init]; 26 | if (self){ 27 | layerChannelCount = 4; 28 | shouldFlipLayerData = NO; 29 | shouldUnpremultiplyLayerData = NO; 30 | flattenedContext = NULL; 31 | flattenedData = nil; 32 | layers = [[NSMutableArray alloc] init]; 33 | } 34 | return self; 35 | } 36 | 37 | - (id)initWithDocumentSize:(CGSize)s 38 | { 39 | self = [self init]; 40 | if (self){ 41 | documentSize = s; 42 | } 43 | return self; 44 | } 45 | 46 | - (void)addLayerWithCGImage:(CGImageRef)image andName:(NSString*)name andOpacity:(float)opacity andOffset:(CGPoint)offset 47 | { 48 | PSDLayer * l = [[PSDLayer alloc] init]; 49 | CGRect imageRegion = CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)); 50 | CGRect screenRegion = CGRectMake(offset.x, offset.y, imageRegion.size.width, imageRegion.size.height); 51 | CGRect drawRegion = CGRectMake(offset.x, offset.y, imageRegion.size.width, imageRegion.size.height); 52 | 53 | if (screenRegion.origin.x + screenRegion.size.width > documentSize.width) 54 | imageRegion.size.width = screenRegion.size.width = documentSize.width - screenRegion.origin.x; 55 | if (screenRegion.origin.y + screenRegion.size.height > documentSize.height) 56 | imageRegion.size.height = screenRegion.size.height = documentSize.height - screenRegion.origin.y; 57 | if (screenRegion.origin.x < 0) { 58 | imageRegion.origin.x = fabs(screenRegion.origin.x); 59 | screenRegion.origin.x = 0; 60 | screenRegion.size.width = imageRegion.size.width = imageRegion.size.width - imageRegion.origin.x; 61 | } 62 | if (screenRegion.origin.y < 0) { 63 | imageRegion.origin.y = fabs(screenRegion.origin.y); 64 | screenRegion.origin.y = 0; 65 | screenRegion.size.height = imageRegion.size.height = imageRegion.size.height - imageRegion.origin.y; 66 | } 67 | 68 | [l setImageData: CGImageGetDataForRegion(image, imageRegion)]; 69 | [l setOpacity: opacity]; 70 | [l setRect: screenRegion]; 71 | [l setName: name]; 72 | [layers addObject: l]; 73 | 74 | if (flattenedData == nil) { 75 | if ((documentSize.width == 0) || (documentSize.height == 0)) 76 | @throw [NSException exceptionWithName:NSGenericException reason:@"You must specify a non-zero documentSize before calling addLayer:" userInfo:nil]; 77 | 78 | if (flattenedContext == NULL) { 79 | flattenedContext = CGBitmapContextCreate(NULL, documentSize.width, documentSize.height, 8, 0, CGImageGetColorSpace(image), kCGBitmapByteOrder32Host|kCGImageAlphaPremultipliedLast); 80 | CGContextSetRGBFillColor(flattenedContext, 1, 1, 1, 1); 81 | CGContextFillRect(flattenedContext, CGRectMake(0, 0, documentSize.width, documentSize.height)); 82 | } 83 | drawRegion.origin.y = documentSize.height - (drawRegion.origin.y + drawRegion.size.height); 84 | CGContextSetAlpha(flattenedContext, opacity); 85 | CGContextDrawImage(flattenedContext, drawRegion, image); 86 | CGContextSetAlpha(flattenedContext, opacity); 87 | } 88 | } 89 | 90 | /* Generates an NSData object representing a PSD image. LayerData should contain an array of NSData 91 | objects representing the RGBA layer data (8 bits per component) and a width and height of size. 92 | flatData should contain the RGBA data of a single image made by flattening all of the layers. */ 93 | 94 | - (void)dealloc 95 | { 96 | if (flattenedContext != NULL) { 97 | CGContextRelease(flattenedContext); 98 | flattenedContext = nil; 99 | } 100 | } 101 | 102 | - (void)preprocess 103 | { 104 | // do we have a flattenedContext that needs to become flattenedData? 105 | if (flattenedData == nil) { 106 | if (flattenedContext) { 107 | CGImageRef i = CGBitmapContextCreateImage(flattenedContext); 108 | flattenedData = CGImageGetDataForRegion(i, CGRectMake(0, 0, documentSize.width, documentSize.height)); 109 | CGImageRelease(i); 110 | } 111 | } 112 | if (flattenedContext) { 113 | CGContextRelease(flattenedContext); 114 | flattenedContext = nil; 115 | 116 | } 117 | 118 | if ((self.shouldFlipLayerData == NO) && (self.shouldUnpremultiplyLayerData == NO)) 119 | return; 120 | 121 | for (PSDLayer * layer in layers) 122 | { 123 | NSData *d = [layer imageData]; 124 | 125 | // sketchy? yes. fast? oh yes. 126 | UInt8 *data = (UInt8 *)[d bytes]; 127 | unsigned long length = [d length]; 128 | 129 | if (self.shouldUnpremultiplyLayerData) { 130 | // perform unpremultiplication 131 | for(long i = 0; i < length; i+=4) { 132 | float a = ((float)data[(i + 3)]) / 255.0; 133 | data[(i+0)] = (int) fmax(0, fmin((float)data[(i+0)] / a, 255)); 134 | data[(i+1)] = (int) fmax(0, fmin((float)data[(i+1)] / a, 255)); 135 | data[(i+2)] = (int) fmax(0, fmin((float)data[(i+2)] / a, 255)); 136 | } 137 | } 138 | 139 | if (self.shouldFlipLayerData) { 140 | // perform flip over vertical axis 141 | for (int x = 0; x < documentSize.width; x++) { 142 | for (int y = 0; y < documentSize.height/2; y++) { 143 | int top_index = (x+y*documentSize.width) * 4; 144 | int bottom_index = (x+(documentSize.height-y-1)*documentSize.width) * 4; 145 | char saved; 146 | 147 | for (int a = 0; a < 4; a++) { 148 | saved = data[top_index+a]; 149 | data[top_index+a] = data[bottom_index+a]; 150 | data[bottom_index+a] = saved; 151 | } 152 | } 153 | } 154 | } 155 | } 156 | } 157 | 158 | - (NSData *)createPSDData 159 | { 160 | char signature8BPS[4] = {'8','B','P','S'}; 161 | char signature8BIM[4] = {'8','B','I','M'}; 162 | 163 | NSMutableData *result = [NSMutableData data]; 164 | 165 | // make sure the user has provided everything we need 166 | if ((layerChannelCount < 3) || ([layers count] == 0)) 167 | @throw [NSException exceptionWithName:NSGenericException 168 | reason:@"Please provide layer data, flattened data and set layer channel count to at least 3." 169 | userInfo:nil]; 170 | 171 | 172 | // modify the input data if necessary 173 | [self preprocess]; 174 | 175 | // FILE HEADER SECTION 176 | // ----------------------------------------------------------------------------------------------- 177 | // write the signature 178 | [result appendBytes:&signature8BPS length:4]; 179 | 180 | // write the version number 181 | [result appendValue:1 withLength:2]; 182 | 183 | // write reserved blank space 184 | [result appendValue:0 withLength:6]; 185 | 186 | // write number of channels 187 | [result appendValue:layerChannelCount withLength:2]; 188 | 189 | // write height then width of the image in pixels 190 | [result appendValue:documentSize.height withLength:4]; 191 | [result appendValue:documentSize.width withLength:4]; 192 | 193 | // write number of bits per channel 194 | [result appendValue:8 withLength:2]; 195 | 196 | // write color mode (3 = RGB) 197 | [result appendValue:3 withLength:2]; 198 | 199 | // COLOR MODE DATA SECTION 200 | // ----------------------------------------------------------------------------------------------- 201 | // write color mode data section 202 | [result appendValue:0 withLength:4]; 203 | 204 | // IMAGE RESOURCES SECTION 205 | // ----------------------------------------------------------------------------------------------- 206 | // write images resources section. This is used to store things like current layer. 207 | NSMutableData *imageResources = [[NSMutableData alloc] init]; 208 | 209 | /* 210 | // Naming the alpha channels isn't necessary, but here's how: 211 | // Apparently those bytes contain 2 pascal strings? I think the last one is zero chars. 212 | [imageResources appendBytes:&signature8BIM length:4]; 213 | [imageResources appendValue:1006 withLength:2]; 214 | [imageResources appendValue:0 withLength:2]; 215 | [imageResources appendValue:19 withLength:4]; 216 | Byte nameBytes[20] = {0x0C,0x54,0x72,0x61,0x6E,0x73,0x70,0x61,0x72,0x65,0x6E,0x63,0x79,0x05,0x45,0x78,0x74,0x72,0x61,0x00}; 217 | [imageResources appendBytes:&nameBytes length:20]; 218 | */ 219 | 220 | // write the resolutionInfo structure. Don't have the definition for this, so we 221 | // have to just paste in the right bytes. 222 | [imageResources appendBytes:&signature8BIM length:4]; 223 | [imageResources appendValue:1005 withLength:2]; 224 | [imageResources appendValue:0 withLength:2]; 225 | [imageResources appendValue:16 withLength:4]; 226 | Byte resBytes[16] = {0x00, 0x48, 0x00, 0x00,0x00,0x01,0x00,0x01,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x01}; 227 | [imageResources appendBytes:&resBytes length:16]; 228 | 229 | // write the current layer structure 230 | [imageResources appendBytes:&signature8BIM length:4]; 231 | [imageResources appendValue:1024 withLength:2]; 232 | [imageResources appendValue:0 withLength:2]; 233 | [imageResources appendValue:2 withLength:4]; 234 | [imageResources appendValue:0 withLength:2]; // current layer = 0 235 | 236 | [result appendValue:[imageResources length] withLength:4]; 237 | [result appendData:imageResources]; 238 | 239 | 240 | // This is for later when we write the transparent top and bottom of the shape 241 | int transparentRowSize = sizeof(Byte) * (int)ceilf(documentSize.width * 4); 242 | Byte *transparentRow = malloc(transparentRowSize); 243 | memset(transparentRow, 0, transparentRowSize); 244 | 245 | NSData *transparentRowData = [NSData dataWithBytesNoCopy:transparentRow 246 | length:transparentRowSize 247 | freeWhenDone:NO]; 248 | NSData *packedTransparentRowData = [transparentRowData packedBitsForRange:NSMakeRange(0, transparentRowSize) skip:4]; 249 | 250 | // LAYER + MASK INFORMATION SECTION 251 | // ----------------------------------------------------------------------------------------------- 252 | // layer and mask information section. contains basic data about each layer (its mask, its channels, 253 | // its layer effects, its annotations, transparency layers, wtf tons of shit.) We need to actually 254 | // create this. 255 | 256 | NSMutableData *layerInfo = [[NSMutableData alloc] init]; 257 | NSMutableArray *layerChannels = [NSMutableArray array]; 258 | NSUInteger layerCount = [layers count]; 259 | 260 | @autoreleasepool { 261 | // write the layer count 262 | [layerInfo appendValue:layerCount withLength:2]; 263 | for (int layer = 0; layer < layerCount; layer++) 264 | { 265 | @autoreleasepool { 266 | NSData *imageData = [[layers objectAtIndex:0] imageData]; 267 | CGRect bounds = [(PSDLayer*)[layers objectAtIndex:0] rect]; 268 | bounds.origin.x = floorf(bounds.origin.x); 269 | bounds.origin.y = floorf(bounds.origin.y); 270 | bounds.size.width = floorf(bounds.size.width); 271 | bounds.size.height = floorf(bounds.size.height); 272 | 273 | // Check the bounds 274 | if (bounds.origin.x < 0 || bounds.origin.y < 0) { 275 | @throw [NSException exceptionWithName:@"LayerOutOfBounds" 276 | reason:[NSString stringWithFormat:@"Layer %i's x or y origin is negative, which is unsupported", layer] 277 | userInfo:nil]; 278 | } 279 | if (bounds.origin.x + bounds.size.width > documentSize.width || 280 | bounds.origin.y + bounds.size.height > documentSize.height) { 281 | @throw [NSException exceptionWithName:@"LayerOutOfBounds" 282 | reason:[NSString stringWithFormat:@"Layer %i's bottom-right corner is beyond the edge of the canvas, which is unsupported", layer] 283 | userInfo:nil]; 284 | } 285 | 286 | int imageRowBytes = bounds.size.width * 4; 287 | 288 | // too much padding is going on here 289 | 290 | NSRange leftPackRange = NSMakeRange(0, (int)bounds.origin.x * 4); 291 | NSData *packedLeftOfShape = [transparentRowData packedBitsForRange:leftPackRange skip:4]; 292 | NSRange rightPackRange = NSMakeRange(0, (int)(documentSize.width - bounds.origin.x - bounds.size.width) * 4); 293 | NSData *packedRightOfShape = [transparentRowData packedBitsForRange:rightPackRange skip:4]; 294 | 295 | for (int channel = 0; channel < layerChannelCount; channel++) 296 | { 297 | NSMutableData *byteCounts = [[NSMutableData alloc] initWithCapacity:documentSize.height * layerChannelCount * 2]; 298 | NSMutableData *scanlines = [[NSMutableData alloc] init]; 299 | 300 | for (int row = 0; row < documentSize.height; row++) 301 | { 302 | // If it's above or below the shape's bounds, just write black with 0-alpha 303 | if (row < (int)bounds.origin.y || row >= (int)(bounds.origin.y + bounds.size.height)) { 304 | [byteCounts appendValue:[packedTransparentRowData length] withLength:2]; 305 | [scanlines appendData:packedTransparentRowData]; 306 | } else { 307 | int byteCount = 0; 308 | 309 | if (bounds.origin.x > 0.01) { 310 | // Append the transparent portion to the left of the shape 311 | [scanlines appendData:packedLeftOfShape]; 312 | byteCount += [packedLeftOfShape length]; 313 | } 314 | 315 | NSRange packRange = NSMakeRange((row - (int)bounds.origin.y) * imageRowBytes + channel, imageRowBytes); 316 | NSData *packed = [imageData packedBitsForRange:packRange skip:4]; 317 | [scanlines appendData:packed]; 318 | byteCount += [packed length]; 319 | 320 | if (bounds.origin.x + bounds.size.width < documentSize.width) { 321 | // Append the transparent portion to the right of the shape 322 | [scanlines appendData:packedRightOfShape]; 323 | byteCount += [packedRightOfShape length]; 324 | } 325 | 326 | [byteCounts appendValue:byteCount withLength:2]; 327 | } 328 | } 329 | NSMutableData *channelData = [[NSMutableData alloc] init]; 330 | // write channel compression format 331 | [channelData appendValue:1 withLength:2]; 332 | // write channel byte counts 333 | [channelData appendData:byteCounts]; 334 | // write channel scanlines 335 | [channelData appendData:scanlines]; 336 | 337 | // add completed channel data to channels array 338 | [layerChannels addObject:channelData]; 339 | } 340 | 341 | // print out top left bottom right 4x4 342 | [layerInfo appendValue:0 withLength:4]; 343 | [layerInfo appendValue:0 withLength:4]; 344 | [layerInfo appendValue:documentSize.height withLength:4]; 345 | [layerInfo appendValue:documentSize.width withLength:4]; 346 | 347 | // print out number of channels in the layer 348 | [layerInfo appendValue:layerChannelCount withLength:2]; 349 | 350 | // print out data about each channel 351 | for (int c = 0; c < 3; c++) { 352 | [layerInfo appendValue:c withLength:2]; 353 | [layerInfo appendValue:[[layerChannels objectAtIndex:c + layer * 4] length] withLength:4]; 354 | } 355 | 356 | // for some reason, the alpha channel is number -1, not 3... 357 | Byte b[2] = {0xFF, 0xFF}; 358 | [layerInfo appendBytes:&b length:2]; 359 | [layerInfo appendValue:[[layerChannels objectAtIndex:3 + layer * 4] length] withLength:4]; 360 | 361 | // print out blend mode signature 362 | [layerInfo appendBytes:&signature8BIM length:4]; 363 | 364 | // print out blend type 365 | char blendModeKey[4] = {'n','o','r','m'}; 366 | [layerInfo appendBytes:&blendModeKey length:4]; 367 | 368 | // print out opacity 369 | int opacity = ceilf([[layers objectAtIndex:0] opacity] * 255.0f); 370 | [layerInfo appendValue:opacity withLength:1]; 371 | 372 | // print out clipping 373 | [layerInfo appendValue:0 withLength:1]; 374 | 375 | // print out flags. I think we're making the layer invisible 376 | [layerInfo appendValue:1 withLength:1]; 377 | [layerInfo appendValue:0 withLength:1]; 378 | 379 | // print out extra data length 380 | [layerInfo appendValue:4+4+16 withLength:4]; 381 | 382 | // print out extra data (mask info, layer name) 383 | [layerInfo appendValue:0 withLength:4]; 384 | [layerInfo appendValue:0 withLength:4]; 385 | 386 | NSString *layerName = [[[layers objectAtIndex:0] name] stringByAppendingString:@" "]; 387 | layerName = [layerName stringByPaddingToLength:15 withString:@" " startingAtIndex:0]; 388 | const char *layerNameCString = [layerName cStringUsingEncoding:NSStringEncodingConversionAllowLossy]; 389 | [layerInfo appendValue:[layerName length] withLength:1]; 390 | [layerInfo appendBytes:layerNameCString length:[layerName length]]; 391 | 392 | [layers removeObjectAtIndex:0]; 393 | } 394 | } 395 | 396 | free(transparentRow); 397 | 398 | // write the channel image data for each layer 399 | while([layerChannels count] > 0) { 400 | [layerInfo appendData:[layerChannels objectAtIndex:0]]; 401 | [layerChannels removeObjectAtIndex:0]; 402 | } 403 | } 404 | 405 | // round to length divisible by 2. 406 | if ([layerInfo length] % 2 != 0) 407 | [layerInfo appendValue:0 withLength:1]; 408 | 409 | // write length of layer and mask information section 410 | [result appendValue:[layerInfo length]+4 withLength:4]; 411 | 412 | // write length of layer info 413 | [result appendValue:[layerInfo length] withLength:4]; 414 | 415 | // write out actual layer info 416 | [result appendData:layerInfo]; 417 | 418 | // This should be required. I'm not sure why it works without it. 419 | // write out empty global layer section (globalLayerMaskLength == 0) 420 | // [self writeValue:0 toData:result withLength:4]; 421 | 422 | // IMAGE DATA SECTION 423 | // ----------------------------------------------------------------------------------------------- 424 | // write compression format = 1 = RLE 425 | [result appendValue:1 withLength:2]; 426 | 427 | // With RLE compression, the image data starts with the byte counts for all of the scan lines (rows * channels) 428 | // with each count stored as a 2-byte value. The RLE compressed data follows with each scan line compressed 429 | // separately. Same as the TIFF standard. 430 | 431 | // in 512x512 image w/ no alpha, there are 3072 scan line bytes. At 2 bytes each, that means 1536 byte counts. 432 | // 1536 = 512 rows * three channels. 433 | 434 | NSMutableData *byteCounts = [NSMutableData dataWithCapacity:documentSize.height * layerChannelCount * 2]; 435 | NSMutableData *scanlines = [NSMutableData data]; 436 | 437 | int imageRowBytes = documentSize.width * 4; 438 | for (int channel = 0; channel < layerChannelCount; channel++) { 439 | @autoreleasepool { 440 | for (int row = 0; row < documentSize.height; row++) { 441 | NSRange packRange = NSMakeRange(row * imageRowBytes + channel, imageRowBytes); 442 | NSData * packed = [flattenedData packedBitsForRange:packRange skip:4]; 443 | [byteCounts appendValue:[packed length] withLength:2]; 444 | [scanlines appendData:packed]; 445 | } 446 | } 447 | } 448 | 449 | // chop off the image data from the original file 450 | [result appendData:byteCounts]; 451 | [result appendData:scanlines]; 452 | 453 | return result; 454 | } 455 | 456 | @end 457 | 458 | 459 | NSData *CGImageGetData(CGImageRef image) { 460 | CGRect region = CGRectZero; 461 | region.size.width = CGImageGetWidth(image); 462 | region.size.height = CGImageGetHeight(image); 463 | return CGImageGetDataForRegion(image, region); 464 | } 465 | 466 | NSData *CGImageGetDataForRegion(CGImageRef image, CGRect region) 467 | { 468 | // Create the bitmap context 469 | CGContextRef context = NULL; 470 | void * bitmapData; 471 | int bitmapByteCount; 472 | int bitmapBytesPerRow; 473 | 474 | // Get image width, height. We'll use the entire image. 475 | int width = region.size.width; 476 | int height = region.size.height; 477 | 478 | // Declare the number of bytes per row. Each pixel in the bitmap in this 479 | // example is represented by 4 bytes; 8 bits each of red, green, blue, and 480 | // alpha. 481 | bitmapBytesPerRow = (width * 4); 482 | bitmapByteCount = (bitmapBytesPerRow * height); 483 | 484 | // Allocate memory for image data. This is the destination in memory 485 | // where any drawing to the bitmap context will be rendered. 486 | // bitmapData = malloc(bitmapByteCount); 487 | bitmapData = calloc(width * height * 4, sizeof(Byte)); 488 | if (bitmapData == NULL) 489 | { 490 | return nil; 491 | } 492 | 493 | // Create the bitmap context. We want pre-multiplied ARGB, 8-bits 494 | // per component. Regardless of what the source image format is 495 | // (CMYK, Grayscale, and so on) it will be converted over to the format 496 | // specified here by CGBitmapContextCreate. 497 | // CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 498 | CGColorSpaceRef colorspace = CGImageGetColorSpace(image); 499 | context = CGBitmapContextCreate(bitmapData, width, height, 8, bitmapBytesPerRow, 500 | colorspace, kCGImageAlphaPremultipliedLast); 501 | // CGColorSpaceRelease(colorspace); 502 | 503 | if (context == NULL) 504 | // error creating context 505 | return nil; 506 | 507 | // Draw the image to the bitmap context. Once we draw, the memory 508 | // allocated for the context for rendering will then contain the 509 | // raw image data in the specified color space. 510 | CGContextSaveGState(context); 511 | 512 | // CGContextTranslateCTM(context, -region.origin.x, -region.origin.y); 513 | // CGContextDrawImage(context, region, image); 514 | 515 | // Draw the image without scaling it to fit the region 516 | CGRect drawRegion; 517 | drawRegion.origin = CGPointZero; 518 | drawRegion.size.width = CGImageGetWidth(image); 519 | drawRegion.size.height = CGImageGetHeight(image); 520 | CGContextTranslateCTM(context, 521 | -region.origin.x + (drawRegion.size.width - region.size.width), 522 | -region.origin.y - (drawRegion.size.height - region.size.height)); 523 | CGContextDrawImage(context, drawRegion, image); 524 | CGContextRestoreGState(context); 525 | 526 | // When finished, release the context 527 | CGContextRelease(context); 528 | 529 | // Now we can get a pointer to the image data associated with the bitmap context. 530 | 531 | NSData *data = [NSData dataWithBytes:bitmapData length:bitmapByteCount]; 532 | free(bitmapData); 533 | 534 | return data; 535 | } 536 | -------------------------------------------------------------------------------- /ScreenToLayersHelper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 266C61751C4EF2AE00CD99A0 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 266C61701C4EF2AE00CD99A0 /* AppDelegate.m */; }; 11 | 266C61771C4EF2AE00CD99A0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 266C61721C4EF2AE00CD99A0 /* main.m */; }; 12 | 266C61781C4EF2AE00CD99A0 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 266C61731C4EF2AE00CD99A0 /* MainMenu.xib */; }; 13 | 266C617C1C4EF2EC00CD99A0 /* Constants.m in Sources */ = {isa = PBXBuildFile; fileRef = 266C617B1C4EF2EC00CD99A0 /* Constants.m */; }; 14 | 267DAFB51C4DDA79008C376F /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 267DAFB41C4DDA79008C376F /* ServiceManagement.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 266C616F1C4EF2AE00CD99A0 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 19 | 266C61701C4EF2AE00CD99A0 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 20 | 266C61711C4EF2AE00CD99A0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 21 | 266C61721C4EF2AE00CD99A0 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | 266C61731C4EF2AE00CD99A0 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; 23 | 266C61741C4EF2AE00CD99A0 /* ScreenToLayersHelper.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = ScreenToLayersHelper.entitlements; sourceTree = ""; }; 24 | 266C617A1C4EF2EC00CD99A0 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ScreenToLayers/Sources/Application/Constants.h; sourceTree = SOURCE_ROOT; }; 25 | 266C617B1C4EF2EC00CD99A0 /* Constants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Constants.m; path = ScreenToLayers/Sources/Application/Constants.m; sourceTree = SOURCE_ROOT; }; 26 | 267DAF971C4DDA4B008C376F /* ScreenToLayersHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScreenToLayersHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 267DAFB41C4DDA79008C376F /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 267DAF941C4DDA4B008C376F /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | 267DAFB51C4DDA79008C376F /* ServiceManagement.framework in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 267DAF8E1C4DDA4B008C376F = { 43 | isa = PBXGroup; 44 | children = ( 45 | 267DAF991C4DDA4B008C376F /* ScreenToLayersHelper */, 46 | 267DAF981C4DDA4B008C376F /* Products */, 47 | ); 48 | sourceTree = ""; 49 | }; 50 | 267DAF981C4DDA4B008C376F /* Products */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 267DAF971C4DDA4B008C376F /* ScreenToLayersHelper.app */, 54 | ); 55 | name = Products; 56 | sourceTree = ""; 57 | }; 58 | 267DAF991C4DDA4B008C376F /* ScreenToLayersHelper */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 266C61741C4EF2AE00CD99A0 /* ScreenToLayersHelper.entitlements */, 62 | 267DAFB41C4DDA79008C376F /* ServiceManagement.framework */, 63 | 266C617A1C4EF2EC00CD99A0 /* Constants.h */, 64 | 266C617B1C4EF2EC00CD99A0 /* Constants.m */, 65 | 266C616F1C4EF2AE00CD99A0 /* AppDelegate.h */, 66 | 266C61701C4EF2AE00CD99A0 /* AppDelegate.m */, 67 | 266C61711C4EF2AE00CD99A0 /* Info.plist */, 68 | 266C61721C4EF2AE00CD99A0 /* main.m */, 69 | 266C61731C4EF2AE00CD99A0 /* MainMenu.xib */, 70 | ); 71 | path = ScreenToLayersHelper; 72 | sourceTree = ""; 73 | }; 74 | /* End PBXGroup section */ 75 | 76 | /* Begin PBXNativeTarget section */ 77 | 267DAF961C4DDA4B008C376F /* ScreenToLayersHelper */ = { 78 | isa = PBXNativeTarget; 79 | buildConfigurationList = 267DAFA81C4DDA4B008C376F /* Build configuration list for PBXNativeTarget "ScreenToLayersHelper" */; 80 | buildPhases = ( 81 | 267DAF931C4DDA4B008C376F /* Sources */, 82 | 267DAF941C4DDA4B008C376F /* Frameworks */, 83 | 267DAF951C4DDA4B008C376F /* Resources */, 84 | ); 85 | buildRules = ( 86 | ); 87 | dependencies = ( 88 | ); 89 | name = ScreenToLayersHelper; 90 | productName = ScreenToLayersHelper; 91 | productReference = 267DAF971C4DDA4B008C376F /* ScreenToLayersHelper.app */; 92 | productType = "com.apple.product-type.application"; 93 | }; 94 | /* End PBXNativeTarget section */ 95 | 96 | /* Begin PBXProject section */ 97 | 267DAF8F1C4DDA4B008C376F /* Project object */ = { 98 | isa = PBXProject; 99 | attributes = { 100 | LastUpgradeCheck = 0720; 101 | ORGANIZATIONNAME = "Jeremy Vizzini"; 102 | TargetAttributes = { 103 | 267DAF961C4DDA4B008C376F = { 104 | CreatedOnToolsVersion = 7.2; 105 | DevelopmentTeam = JVTX6KC453; 106 | SystemCapabilities = { 107 | com.apple.Sandbox = { 108 | enabled = 1; 109 | }; 110 | }; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 267DAF921C4DDA4B008C376F /* Build configuration list for PBXProject "ScreenToLayersHelper" */; 115 | compatibilityVersion = "Xcode 3.2"; 116 | developmentRegion = English; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 267DAF8E1C4DDA4B008C376F; 123 | productRefGroup = 267DAF981C4DDA4B008C376F /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 267DAF961C4DDA4B008C376F /* ScreenToLayersHelper */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXResourcesBuildPhase section */ 133 | 267DAF951C4DDA4B008C376F /* Resources */ = { 134 | isa = PBXResourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 266C61781C4EF2AE00CD99A0 /* MainMenu.xib in Resources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXSourcesBuildPhase section */ 144 | 267DAF931C4DDA4B008C376F /* Sources */ = { 145 | isa = PBXSourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 266C61771C4EF2AE00CD99A0 /* main.m in Sources */, 149 | 266C61751C4EF2AE00CD99A0 /* AppDelegate.m in Sources */, 150 | 266C617C1C4EF2EC00CD99A0 /* Constants.m in Sources */, 151 | ); 152 | runOnlyForDeploymentPostprocessing = 0; 153 | }; 154 | /* End PBXSourcesBuildPhase section */ 155 | 156 | /* Begin XCBuildConfiguration section */ 157 | 267DAFA61C4DDA4B008C376F /* Debug */ = { 158 | isa = XCBuildConfiguration; 159 | buildSettings = { 160 | ALWAYS_SEARCH_USER_PATHS = NO; 161 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 162 | CLANG_CXX_LIBRARY = "libc++"; 163 | CLANG_ENABLE_MODULES = YES; 164 | CLANG_ENABLE_OBJC_ARC = YES; 165 | CLANG_WARN_BOOL_CONVERSION = YES; 166 | CLANG_WARN_CONSTANT_CONVERSION = YES; 167 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 168 | CLANG_WARN_EMPTY_BODY = YES; 169 | CLANG_WARN_ENUM_CONVERSION = YES; 170 | CLANG_WARN_INT_CONVERSION = YES; 171 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 172 | CLANG_WARN_UNREACHABLE_CODE = YES; 173 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 174 | CODE_SIGN_IDENTITY = "-"; 175 | COPY_PHASE_STRIP = NO; 176 | DEBUG_INFORMATION_FORMAT = dwarf; 177 | ENABLE_STRICT_OBJC_MSGSEND = YES; 178 | ENABLE_TESTABILITY = YES; 179 | GCC_C_LANGUAGE_STANDARD = gnu99; 180 | GCC_DYNAMIC_NO_PIC = NO; 181 | GCC_NO_COMMON_BLOCKS = YES; 182 | GCC_OPTIMIZATION_LEVEL = 0; 183 | GCC_PREPROCESSOR_DEFINITIONS = ( 184 | "DEBUG=1", 185 | "$(inherited)", 186 | ); 187 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 188 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 189 | GCC_WARN_UNDECLARED_SELECTOR = YES; 190 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 191 | GCC_WARN_UNUSED_FUNCTION = YES; 192 | GCC_WARN_UNUSED_VARIABLE = YES; 193 | MACOSX_DEPLOYMENT_TARGET = 10.11; 194 | MTL_ENABLE_DEBUG_INFO = YES; 195 | ONLY_ACTIVE_ARCH = YES; 196 | SDKROOT = macosx; 197 | }; 198 | name = Debug; 199 | }; 200 | 267DAFA71C4DDA4B008C376F /* Release */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ALWAYS_SEARCH_USER_PATHS = NO; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 205 | CLANG_CXX_LIBRARY = "libc++"; 206 | CLANG_ENABLE_MODULES = YES; 207 | CLANG_ENABLE_OBJC_ARC = YES; 208 | CLANG_WARN_BOOL_CONVERSION = YES; 209 | CLANG_WARN_CONSTANT_CONVERSION = YES; 210 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 211 | CLANG_WARN_EMPTY_BODY = YES; 212 | CLANG_WARN_ENUM_CONVERSION = YES; 213 | CLANG_WARN_INT_CONVERSION = YES; 214 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 215 | CLANG_WARN_UNREACHABLE_CODE = YES; 216 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 217 | CODE_SIGN_IDENTITY = "-"; 218 | COPY_PHASE_STRIP = NO; 219 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 220 | ENABLE_NS_ASSERTIONS = NO; 221 | ENABLE_STRICT_OBJC_MSGSEND = YES; 222 | GCC_C_LANGUAGE_STANDARD = gnu99; 223 | GCC_NO_COMMON_BLOCKS = YES; 224 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 225 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 226 | GCC_WARN_UNDECLARED_SELECTOR = YES; 227 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 228 | GCC_WARN_UNUSED_FUNCTION = YES; 229 | GCC_WARN_UNUSED_VARIABLE = YES; 230 | MACOSX_DEPLOYMENT_TARGET = 10.11; 231 | MTL_ENABLE_DEBUG_INFO = NO; 232 | SDKROOT = macosx; 233 | }; 234 | name = Release; 235 | }; 236 | 267DAFA91C4DDA4B008C376F /* Debug */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | CODE_SIGN_ENTITLEMENTS = ScreenToLayersHelper/ScreenToLayersHelper.entitlements; 240 | CODE_SIGN_IDENTITY = "Mac Developer"; 241 | COMBINE_HIDPI_IMAGES = YES; 242 | INFOPLIST_FILE = ScreenToLayersHelper/Info.plist; 243 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 244 | MACOSX_DEPLOYMENT_TARGET = 10.10; 245 | PRODUCT_BUNDLE_IDENTIFIER = com.jeremyvizzini.screentolayers.osx.helper; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | SKIP_INSTALL = YES; 248 | }; 249 | name = Debug; 250 | }; 251 | 267DAFAA1C4DDA4B008C376F /* Release */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | CODE_SIGN_ENTITLEMENTS = ScreenToLayersHelper/ScreenToLayersHelper.entitlements; 255 | CODE_SIGN_IDENTITY = "Mac Developer"; 256 | COMBINE_HIDPI_IMAGES = YES; 257 | COPY_PHASE_STRIP = YES; 258 | INFOPLIST_FILE = ScreenToLayersHelper/Info.plist; 259 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 260 | MACOSX_DEPLOYMENT_TARGET = 10.10; 261 | PRODUCT_BUNDLE_IDENTIFIER = com.jeremyvizzini.screentolayers.osx.helper; 262 | PRODUCT_NAME = "$(TARGET_NAME)"; 263 | SKIP_INSTALL = YES; 264 | }; 265 | name = Release; 266 | }; 267 | /* End XCBuildConfiguration section */ 268 | 269 | /* Begin XCConfigurationList section */ 270 | 267DAF921C4DDA4B008C376F /* Build configuration list for PBXProject "ScreenToLayersHelper" */ = { 271 | isa = XCConfigurationList; 272 | buildConfigurations = ( 273 | 267DAFA61C4DDA4B008C376F /* Debug */, 274 | 267DAFA71C4DDA4B008C376F /* Release */, 275 | ); 276 | defaultConfigurationIsVisible = 0; 277 | defaultConfigurationName = Release; 278 | }; 279 | 267DAFA81C4DDA4B008C376F /* Build configuration list for PBXNativeTarget "ScreenToLayersHelper" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | 267DAFA91C4DDA4B008C376F /* Debug */, 283 | 267DAFAA1C4DDA4B008C376F /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | defaultConfigurationName = Release; 287 | }; 288 | /* End XCConfigurationList section */ 289 | }; 290 | rootObject = 267DAF8F1C4DDA4B008C376F /* Project object */; 291 | } 292 | -------------------------------------------------------------------------------- /ScreenToLayersHelper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ScreenToLayersHelper 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ScreenToLayersHelper 4 | // 5 | // Created by Jeremy Vizzini. 6 | // This software is released subject to licensing conditions as detailed in Licence.txt. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "Constants.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)notification { 19 | BOOL alreadyRunning = NO; 20 | NSArray *running = [[NSWorkspace sharedWorkspace] runningApplications]; 21 | for (NSRunningApplication *app in running) { 22 | if ([[app bundleIdentifier] isEqualToString:ApplicationID]) { 23 | alreadyRunning = YES; 24 | break; 25 | } 26 | } 27 | 28 | if (!alreadyRunning) { 29 | NSString *path = [[NSBundle mainBundle] bundlePath]; 30 | NSMutableArray *components = [[path pathComponents] mutableCopy]; 31 | [components removeLastObject]; // Helper app name 32 | [components removeLastObject]; // LoginItems folder 33 | [components removeLastObject]; // Library folder 34 | [components removeLastObject]; // Contents folder 35 | [components removeLastObject]; // Main app folder 36 | [components addObject:[ApplicationName stringByAppendingPathExtension:@"app"]]; 37 | NSString *newPath = [NSString pathWithComponents:components]; 38 | [[NSWorkspace sharedWorkspace] launchApplication:newPath]; 39 | } 40 | [NSApp terminate:nil]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSBackgroundOnly 24 | 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2016 Jeremy Vizzini. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/ScreenToLayersHelper.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ScreenToLayersHelper/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ScreenToLayersHelper 4 | // 5 | // Created by Jeremy Vizzini on 19/01/16. 6 | // Copyright © 2016 Jeremy Vizzini. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ScreenToLayersTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ScreenToLayersTests/ScreenToLayersTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenToLayersTests.m 3 | // ScreenToLayersTests 4 | // 5 | // Created by Jeremy Vizzini on 17/01/16. 6 | // Copyright © 2016 Jeremy Vizzini. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ScreenToLayersTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ScreenToLayersTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Website/assets/fonts/elegant-icons/ElegantIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/elegant-icons/ElegantIcons.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-black/lato-black-0fdcfb7bc888d2aff696dda853bc4ddc8d0cdf8655f7cab2f0263bbe189e160d.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-black/lato-black-0fdcfb7bc888d2aff696dda853bc4ddc8d0cdf8655f7cab2f0263bbe189e160d.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-black/lato-black-62398f940a9564361022ba6d5fbbaad7cb600b3d7ef13a259a7bc4c859dd4f44.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-black/lato-black-62398f940a9564361022ba6d5fbbaad7cb600b3d7ef13a259a7bc4c859dd4f44.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-black/lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-black/lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-black/lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-black/lato-black-c938aee2a794e1ce6b048340d98d5b951c23ee91c9e6d466bdd53128d8755af4.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-black/lato-black-ff00636ea86b2c0d42f9b810b4f8304468ede38a3bd1bb14ac85086c879123f5.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-black/lato-black-ff00636ea86b2c0d42f9b810b4f8304468ede38a3bd1bb14ac85086c879123f5.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-blackitalic/lato-blackitalic-5c30baab619437ce5d1db90496ba62e511194b0247aaa0d9d4eb1c7eff9e9cb9.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-blackitalic/lato-blackitalic-5c30baab619437ce5d1db90496ba62e511194b0247aaa0d9d4eb1c7eff9e9cb9.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-blackitalic/lato-blackitalic-b91fc91ef31bcedf97c528d7ecc3b2cfc9a3f6201017827647641a5fdcf15332.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-blackitalic/lato-blackitalic-b91fc91ef31bcedf97c528d7ecc3b2cfc9a3f6201017827647641a5fdcf15332.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-blackitalic/lato-blackitalic-be00fa70983ec52b18b98e1b9f172432ee941c62ceddd06e945a71f8f30b38f7.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-blackitalic/lato-blackitalic-be00fa70983ec52b18b98e1b9f172432ee941c62ceddd06e945a71f8f30b38f7.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-blackitalic/lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-blackitalic/lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-blackitalic/lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-blackitalic/lato-blackitalic-c03412495d80d9af7969ebc02fe79dfc492ec37536f0c544702d079a093b4c91.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bold/lato-bold-2db60403ee96a301b6290c255ef74653fe8dc2b4251ee66ed4e939cd05dbc84e.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bold/lato-bold-2db60403ee96a301b6290c255ef74653fe8dc2b4251ee66ed4e939cd05dbc84e.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bold/lato-bold-4013e068df10593a69fae75d89a24b170951500db393cf66f89dd2eff4325bad.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bold/lato-bold-4013e068df10593a69fae75d89a24b170951500db393cf66f89dd2eff4325bad.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bold/lato-bold-4c04f7890211bca9a31919ee49e1250835ab842c3a0a6321ce7af1e3b38beee2.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bold/lato-bold-4c04f7890211bca9a31919ee49e1250835ab842c3a0a6321ce7af1e3b38beee2.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bold/lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bold/lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bold/lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bold/lato-bold-51ae36dcfb7132b4fcab34278ae4212721da7165dfe1cddc3e04262dd37b0c2d.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bolditalic/lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bolditalic/lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bolditalic/lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bolditalic/lato-bolditalic-2d34e72fd82cd4d67aae0718cf437404af3f372efec0a557f1115d4f861a340e.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bolditalic/lato-bolditalic-70f233b8c3d0ca4baa08edb05d0aad645ebd8785f3b9008a7ddb0cdbc0999355.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bolditalic/lato-bolditalic-70f233b8c3d0ca4baa08edb05d0aad645ebd8785f3b9008a7ddb0cdbc0999355.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bolditalic/lato-bolditalic-7c82caec73fedc2f2a2ac7b555a18d996a3c002e4c8bf4ad98f5eabcc00911a6.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bolditalic/lato-bolditalic-7c82caec73fedc2f2a2ac7b555a18d996a3c002e4c8bf4ad98f5eabcc00911a6.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-bolditalic/lato-bolditalic-cbe6e3a67d25024006b81fc63c7c6f939cd6e8b6710abe1b7f57a71f8fb0d2cd.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-bolditalic/lato-bolditalic-cbe6e3a67d25024006b81fc63c7c6f939cd6e8b6710abe1b7f57a71f8fb0d2cd.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairline/lato-hairline-0383396e9c2fa6a01ddd23a6bbe2c2e080c949c4870e7a2efa0aa1df65ce2d3f.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairline/lato-hairline-0383396e9c2fa6a01ddd23a6bbe2c2e080c949c4870e7a2efa0aa1df65ce2d3f.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairline/lato-hairline-8cae7ee6d8b1c9b4931074bc6db6d4d91c4cf58b09a6fd01ea1e3111a23bde6f.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairline/lato-hairline-8cae7ee6d8b1c9b4931074bc6db6d4d91c4cf58b09a6fd01ea1e3111a23bde6f.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairline/lato-hairline-8cd6e1c4ff74bd2a6a487cd6010a01d15550fab64e1301e0db7ba7cd475502c1.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairline/lato-hairline-8cd6e1c4ff74bd2a6a487cd6010a01d15550fab64e1301e0db7ba7cd475502c1.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairline/lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairline/lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairline/lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairline/lato-hairline-95224844ba1ca3d5ad5ceb3769905f6c8fcd3f50d5e950ecf6a58551eee55c61.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-02e8289425a81cc1f780d549b9dda6f0ad1bc1ad6a9752ee860a33324a1e3a73.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-13b8e2ec7c8bdb58c6b23559e9b361367d80167d2e630f413bc4d381aff98f1f.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-13b8e2ec7c8bdb58c6b23559e9b361367d80167d2e630f413bc4d381aff98f1f.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-531ef4d2da6e541d10fb2ec2b75c5136cfee31965fcf1184b70ada55c88e82e4.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-531ef4d2da6e541d10fb2ec2b75c5136cfee31965fcf1184b70ada55c88e82e4.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-b7d7d0e1816bc776d99eda748bc01312005fd497e3f5b91573cc291ef5ddb2ea.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-hairlineitalic/lato-hairlineitalic-b7d7d0e1816bc776d99eda748bc01312005fd497e3f5b91573cc291ef5ddb2ea.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavy/lato-heavy-26e51949df663e17fe24e240368aa46e6a269cf07ce45cbfee2bf6d10efa712b.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavy/lato-heavy-26e51949df663e17fe24e240368aa46e6a269cf07ce45cbfee2bf6d10efa712b.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavy/lato-heavy-3f519229220cb477506e28c855bef4bc0eca6978807c6da90745601e30e2a7ba.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavy/lato-heavy-3f519229220cb477506e28c855bef4bc0eca6978807c6da90745601e30e2a7ba.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavy/lato-heavy-b61b8c1f4ecea7b5b6a80c0e2db37c306e8c3afc280e6bf3fff8fb3f36f225aa.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavy/lato-heavy-b61b8c1f4ecea7b5b6a80c0e2db37c306e8c3afc280e6bf3fff8fb3f36f225aa.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavy/lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavy/lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavy/lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavy/lato-heavy-ec5bf34682457a2fff0469c7b8bc864bec16678b058c8c4e8dafae6c1cadd7a7.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1a9978e061e650f61d65d3b1890d0a470bf05f01efddb2992d951c783b6b48f5.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1e9c13e0236e0509dd5e7f53eb8f0588a8a6ce56de853263412a7fb3926394cf.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-1e9c13e0236e0509dd5e7f53eb8f0588a8a6ce56de853263412a7fb3926394cf.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-303ad9fdca6b278c230dac7bc076a8fa28b69c95249a6c62c48b73fa2da9a404.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-303ad9fdca6b278c230dac7bc076a8fa28b69c95249a6c62c48b73fa2da9a404.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-910a7d953f7f85ab9baf9a24ed474a1b232b601dda7e698e5189e77fb531fa25.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-heavyitalic/lato-heavyitalic-910a7d953f7f85ab9baf9a24ed474a1b232b601dda7e698e5189e77fb531fa25.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-italic/lato-italic-09c7fca6b6ec95d8caf5a3cd86bb625f4a943dca54d0d1bd9cf4ee4296d3b434.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-italic/lato-italic-09c7fca6b6ec95d8caf5a3cd86bb625f4a943dca54d0d1bd9cf4ee4296d3b434.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-italic/lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-italic/lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-italic/lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-italic/lato-italic-585c35317d366f81c9573d219134c6d8f59e3e44a898ac07117fbfa8fe6a162f.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-italic/lato-italic-e37ec1819c1ab85df6e2069a90d2d686ce211cf1d83e70a1ff2c3eed66b679da.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-italic/lato-italic-e37ec1819c1ab85df6e2069a90d2d686ce211cf1d83e70a1ff2c3eed66b679da.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-italic/lato-italic-fdccaa222969116965e47e9caee632698eba2e10263b4ece35e0c35ef5ef7013.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-italic/lato-italic-fdccaa222969116965e47e9caee632698eba2e10263b4ece35e0c35ef5ef7013.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-light/lato-light-2db698035576dcb0ba8a5c8c70d53b553b92882c9b1f5a9483618b98aa3a9fb1.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-light/lato-light-2db698035576dcb0ba8a5c8c70d53b553b92882c9b1f5a9483618b98aa3a9fb1.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-light/lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-light/lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-light/lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-light/lato-light-341d4f87acab07b8c1dc0ff3f8e632ad47a8b47a8cedf8869f3a1fbb92c4ac8c.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-light/lato-light-4c8fca932790d59f62df83d77cf1c4ec3de1b9a372f61e81a1746b62fba36ed7.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-light/lato-light-4c8fca932790d59f62df83d77cf1c4ec3de1b9a372f61e81a1746b62fba36ed7.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-light/lato-light-7efd0b09b9f1934d99449269dbb4ec5b8ca917b18fb18cfd0852c48a05d32cff.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-light/lato-light-7efd0b09b9f1934d99449269dbb4ec5b8ca917b18fb18cfd0852c48a05d32cff.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-lightitalic/lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-lightitalic/lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-lightitalic/lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-lightitalic/lato-lightitalic-93c2296ffa5d58f3bcaf1594b706e710225319868992232dd27ab6369a737e8a.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-lightitalic/lato-lightitalic-d9fc1c1da023580642e39b9ef87c2cfbcc1d6508919306274fee3403dc0dc159.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-lightitalic/lato-lightitalic-d9fc1c1da023580642e39b9ef87c2cfbcc1d6508919306274fee3403dc0dc159.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-lightitalic/lato-lightitalic-e33518d1874f4cb4a004d52f1ef9f17b766422213249a225990cc229c938d86d.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-lightitalic/lato-lightitalic-e33518d1874f4cb4a004d52f1ef9f17b766422213249a225990cc229c938d86d.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-medium/lato-medium-83f6d6134d3121d9ac20cadff1b79dfbfe7593d78edaaa1bd2c0014e4d6bb51f.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-medium/lato-medium-83f6d6134d3121d9ac20cadff1b79dfbfe7593d78edaaa1bd2c0014e4d6bb51f.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-medium/lato-medium-af767dc73c5b662830c2ac04403a801bfb1ac58c61a54879e0cf7bfdf7204648.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-medium/lato-medium-af767dc73c5b662830c2ac04403a801bfb1ac58c61a54879e0cf7bfdf7204648.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-medium/lato-medium-c199213882b79fe118e73b1f490b534a2be2eb6485bccfd8137b934a1cc66cbd.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-medium/lato-medium-c199213882b79fe118e73b1f490b534a2be2eb6485bccfd8137b934a1cc66cbd.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-medium/lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-medium/lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-medium/lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-medium/lato-medium-dfbd04b52f013fd274133ac007e2e3c005ce51c0d26c3602021e31d26a80fed7.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-4242fdcecc77250d348cb9d247df5ef3fd7c18bd5ed5a7fb1f9c24150c8a7500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-4242fdcecc77250d348cb9d247df5ef3fd7c18bd5ed5a7fb1f9c24150c8a7500.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-525c8ca6df88d1a3207eabfb0cdb590918c1228d0969482e1ad0e1b35d58c349.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-525c8ca6df88d1a3207eabfb0cdb590918c1228d0969482e1ad0e1b35d58c349.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-8f447edcd2d39ee7af8aa0b06d04a8fd2e27dbff93b625c0e6e9f3d8b04e9a39.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-8f447edcd2d39ee7af8aa0b06d04a8fd2e27dbff93b625c0e6e9f3d8b04e9a39.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-mediumitalic/lato-mediumitalic-c8b1bc2f29e333090960c4f907f56151a99e1727acb82f52739dae13fd62e960.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-regular/lato-regular-4d1b04750516461935cc4380bd441308d5eae5f286e039a05993a7ab64cfdef3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-regular/lato-regular-4d1b04750516461935cc4380bd441308d5eae5f286e039a05993a7ab64cfdef3.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-regular/lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-regular/lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-regular/lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-regular/lato-regular-a799adc3b95a04b1fbf6966306dbbfd1aad62f09a92c1f81cdf3aadc09b1cba4.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-regular/lato-regular-bac8fd7529ad14199431bf9b56c388af416c02c1680cfa398cfb9cedcdcd3eef.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-regular/lato-regular-bac8fd7529ad14199431bf9b56c388af416c02c1680cfa398cfb9cedcdcd3eef.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-regular/lato-regular-dc3da5f3b2066ffd80e16409739c3f46b854159b3da3c51add3f1575e9871ee6.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-regular/lato-regular-dc3da5f3b2066ffd80e16409739c3f46b854159b3da3c51add3f1575e9871ee6.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibold/lato-semibold-15f0dbfdc7e0142e35e0cfad279b9162494ebe5d2d2f0dcd19b079c4e4a48682.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibold/lato-semibold-15f0dbfdc7e0142e35e0cfad279b9162494ebe5d2d2f0dcd19b079c4e4a48682.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibold/lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibold/lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibold/lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibold/lato-semibold-3fb9f1890c36389617c91af135fd5961dd496dfb2862885aebc48d1f4c04ddb3.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibold/lato-semibold-7fe01f8fb9483d0cb5c8906d05a67b9e507e103bae774432ca46969eea5c232b.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibold/lato-semibold-7fe01f8fb9483d0cb5c8906d05a67b9e507e103bae774432ca46969eea5c232b.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibold/lato-semibold-f8f3aac8450bf098f51c3592ac8183464224256f8e46d3859c6a76cc11d59474.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibold/lato-semibold-f8f3aac8450bf098f51c3592ac8183464224256f8e46d3859c6a76cc11d59474.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-6acaf70fafb34a047b79a7e8f74d4dc73aba0f535de13001e6fc774cbda44df4.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-6acaf70fafb34a047b79a7e8f74d4dc73aba0f535de13001e6fc774cbda44df4.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-769c1c6ea52389fdeecdb34b2bac4d7a88f1f87fcd616b5c1d4659a783bd8c49.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-bd09c611a72e6a286889bf430371e34bd7492e9e219366d55f977aea27beb549.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-bd09c611a72e6a286889bf430371e34bd7492e9e219366d55f977aea27beb549.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-d71659bee75208d433fb0739196567820055dfdde8464fedd54072c074dffa9a.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-semibolditalic/lato-semibolditalic-d71659bee75208d433fb0739196567820055dfdde8464fedd54072c074dffa9a.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thin/lato-thin-3805c2094ccefe9effe129d67fe26d14c950af5564696099c6e02e7ef3e1c127.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thin/lato-thin-3805c2094ccefe9effe129d67fe26d14c950af5564696099c6e02e7ef3e1c127.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thin/lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thin/lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thin/lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thin/lato-thin-46f175a71453d2fd550b24ba66af3cc1becb8856410ab5622636c928906a2ff3.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thin/lato-thin-cf486941963fd625a34b4502f3eaa305856fc2441193a5f8c7aa86ede26153f1.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thin/lato-thin-cf486941963fd625a34b4502f3eaa305856fc2441193a5f8c7aa86ede26153f1.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thin/lato-thin-d1a9b702aab8df85f75db13a4d5d5b70949eb8211f16ceda058efbd6c47bf681.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thin/lato-thin-d1a9b702aab8df85f75db13a4d5d5b70949eb8211f16ceda058efbd6c47bf681.woff -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thinitalic/lato-thinitalic-4d6857db5ccf5ae8493c776a05700f28dd77ba206bceb0d5dc1b2c0ad1b85e40.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thinitalic/lato-thinitalic-4d6857db5ccf5ae8493c776a05700f28dd77ba206bceb0d5dc1b2c0ad1b85e40.woff2 -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thinitalic/lato-thinitalic-5c8b705d5ef0fe26552ee5224c2cf1150a48697c7b5799b52ac3c3d0e7a49cbc.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thinitalic/lato-thinitalic-5c8b705d5ef0fe26552ee5224c2cf1150a48697c7b5799b52ac3c3d0e7a49cbc.ttf -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thinitalic/lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e-.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thinitalic/lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e-.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thinitalic/lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thinitalic/lato-thinitalic-af02b66354503a6630b3e5451c2412bca5ea2993d333960498ad4eab3b8f0e0e.eot -------------------------------------------------------------------------------- /Website/assets/fonts/lato-thinitalic/lato-thinitalic-b9d520845392f53b55a10c8fe53bb548efeb81163d130677e834457afcbe3c9c.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/fonts/lato-thinitalic/lato-thinitalic-b9d520845392f53b55a10c8fe53bb548efeb81163d130677e834457afcbe3c9c.woff -------------------------------------------------------------------------------- /Website/assets/images/apple-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Website/assets/images/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/cover.jpg -------------------------------------------------------------------------------- /Website/assets/images/download-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Slice 1 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Website/assets/images/github-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Fill 3 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Website/assets/images/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_128x128.png -------------------------------------------------------------------------------- /Website/assets/images/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_128x128@2x.png -------------------------------------------------------------------------------- /Website/assets/images/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_16x16.png -------------------------------------------------------------------------------- /Website/assets/images/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_16x16@2x.png -------------------------------------------------------------------------------- /Website/assets/images/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_256x256.png -------------------------------------------------------------------------------- /Website/assets/images/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_256x256@2x.png -------------------------------------------------------------------------------- /Website/assets/images/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_32x32.png -------------------------------------------------------------------------------- /Website/assets/images/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_32x32@2x.png -------------------------------------------------------------------------------- /Website/assets/images/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_512x512.png -------------------------------------------------------------------------------- /Website/assets/images/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/icon_512x512@2x.png -------------------------------------------------------------------------------- /Website/assets/images/screen-export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/screen-export.png -------------------------------------------------------------------------------- /Website/assets/images/screen-export@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/screen-export@2x.png -------------------------------------------------------------------------------- /Website/assets/images/screen-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/screen-list.png -------------------------------------------------------------------------------- /Website/assets/images/screen-list@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/assets/images/screen-list@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit.zip -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/AppStore/screen1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/AppStore/screen1.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/AppStore/screen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/AppStore/screen2.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/AppStore/screen3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/AppStore/screen3.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_128x128.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_128x128@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_16x16.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_16x16@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_256x256.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_256x256@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_32x32.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_32x32@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_512x512.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Icons/icon_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Icons/icon_512x512@2x.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Screenshots/screen-export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Screenshots/screen-export.png -------------------------------------------------------------------------------- /Website/downloads/screentolayers-presskit/Screenshots/screen-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duyquoc/ScreenToLayers/b4429336941d8cdd5438c8d59eb00a4572648968/Website/downloads/screentolayers-presskit/Screenshots/screen-list.png -------------------------------------------------------------------------------- /Website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ScreenToLayers 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
ScreenToLayers – Easily export your screen into a layered PSD file
32 | 33 |
Requires macOS Yosemite or later
34 | 35 | 47 |
48 |
49 | 50 |
51 |
52 |
Integrated to your environment.
53 |
The application is located in the menu bar to give you a quick access everywhere. The images are exported in a PSD file which can be opened with the most used graphic softwares such as Photoshop, Pixelmator and Acorn.
54 | 55 |
56 |
57 | 58 |
59 |
60 |
Keep only what you want.
61 |
An alternative interface is provided to capture only what you need. You can select a single component and export only this one. Moreover, you can also choose to disable advanced settings as the shadow or the framing.
62 | 63 |
64 |
65 | 66 |
67 |
68 |
Get ScreenToLayers right now!
69 |
You'll get started in no time and discover how ScreenToLayers will make your life easier.
70 |
71 |
72 | 73 |
ScreenToLayers for Mac
74 |
Designed for latest versions of macOS.
Required OS X 10.10 or later.
75 | 87 |
88 |
89 |
90 |
91 | 92 |
93 |
94 |
We are always here to help – feel free to contact us and stay tuned!
95 |
96 |
97 |  Help & Support 98 |
99 |
100 |  Contact Team 101 |
102 |
103 |  Press Kit 104 |
105 |
106 | 107 |
108 | 109 |
110 |
111 |
112 | 113 | 114 | 115 | --------------------------------------------------------------------------------