appjam 0.1.8.8 → 0.1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -62
- data/lib/appjam/generators/gist.yml +1 -1
- data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.pbxproj +1166 -482
- data/lib/appjam/generators/templates/blank/EiffelApplication.xcodeproj/project.xcworkspace/xcuserdata/eiffel.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/EiffelApplication-Prefix.pch.tt +26 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.h +52 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenu.m +412 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.h +44 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/AwesomeMenuItem.m +97 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-addbutton@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/bg-menuitem@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus-highlighted@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-plus@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/AwesomeMenu/Images/icon-star@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.h +167 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/CMPopTipView/CMPopTipView.m +639 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.h +97 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.m +1080 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.h +451 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/MBProgressHUD/MBProgressHUD.m +865 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.h +42 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FacingView.m +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.h +90 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/FoldView.m +316 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.h +104 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/MultiFoldView.m +516 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldConstants.h +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.h +18 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldNavigationController.m +88 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_left@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldResources.bundle/swipe_guide_right@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldSwipeHintView.m +76 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.h +131 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/PaperFoldView.m +941 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide.psd +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/Resources/swipe_guide2.psd +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.h +46 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/ShadowView.m +82 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.h +39 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/TouchThroughUIView.m +72 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.h +42 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/PaperFold/UIView+Screenshot.m +100 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.h +34 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/NSBubbleData.m +140 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.h +17 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleHeaderTableViewCell.m +57 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.h +30 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableView.m +233 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.h +19 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewCell.m +122 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTableViewDataSource.h +24 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.h +20 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/UIBubbleTypingTableViewCell.m +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleMine@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/bubbleSomeone@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/missingAvatar@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingMine@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIBubbleTableView/images/typingSomeone@2x.png +0 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.h +124 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIGlossyButton.m +545 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.h +22 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/UIGlossyButton/UIView+LayerEffects.m +32 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.h +344 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFIncrementalStore.m +848 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.h +135 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/AFIncrementalStore/AFRESTClient.m +441 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.h +40 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/NSString+InflectorKit.m +36 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.h +76 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/InflectorKit/TTTStringInflector.m +270 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.h +95 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/MKAnnotationView+WebCache.m +78 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.h +144 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDImageCache.m +311 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.h +40 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageCompat.m +54 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.h +18 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDecoder.m +70 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.h +102 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloader.m +226 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageDownloaderOperation.m +339 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.h +167 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageManager.m +244 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImageOperation.h +15 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.h +58 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/SDWebImagePrefetcher.m +127 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.h +173 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIButton+WebCache.m +129 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.h +140 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/frameworks/SDWebImage/UIImageView+WebCache.m +84 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationProgram.h +28 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationSequence.h +28 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/CPAnimationStep.h +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationProgram.m +100 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationSequence.m +85 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CPAnimationSequence/private/CPAnimationStep.m +122 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.h +1074 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaAsyncSocket/GCDAsyncSocket.m +7430 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.h +14 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDData.m +158 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.h +12 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDNumber.m +88 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.h +56 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Categories/DDRange.m +104 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.h +45 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPAuthenticationRequest.m +195 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.h +119 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPConnection.m +2708 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPLogging.h +136 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.h +48 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPMessage.m +113 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPResponse.h +149 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.h +205 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/HTTPServer.m +772 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.h +65 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartFormDataParser.m +529 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.h +33 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeader.m +86 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.h +23 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Mime/MultipartMessageHeaderField.m +211 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.h +75 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPAsyncFileResponse.m +405 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.h +13 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDataResponse.m +79 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.h +52 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPDynamicFileResponse.m +292 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.h +9 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPErrorResponse.m +38 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.h +25 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPFileResponse.m +237 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.h +12 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/Responses/HTTPRedirectResponse.m +73 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.h +105 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Core/WebSocket.m +791 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.h +7 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVConnection.m +160 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.h +11 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DAVResponse.m +372 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.h +7 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/DELETEResponse.m +49 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.h +8 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/CocoaHTTPServer/Extensions/WebDAV/PUTResponse.m +69 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.h +54 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHpple.m +102 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.h +103 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/TFHppleElement.m +200 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.h +10 -0
- data/lib/appjam/generators/templates/blank/EiffelApplication/libs/toolkit/hpple/XPathQuery.m +197 -0
- data/lib/appjam/version.rb +1 -1
- metadata +164 -3
data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.h
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
//
|
2
|
+
// FXLabel.h
|
3
|
+
//
|
4
|
+
// Version 1.5 beta
|
5
|
+
//
|
6
|
+
// Created by Nick Lockwood on 20/08/2011.
|
7
|
+
// Copyright 2011 Charcoal Design
|
8
|
+
//
|
9
|
+
// Distributed under the permissive zlib license
|
10
|
+
// Get the latest version from here:
|
11
|
+
//
|
12
|
+
// https://github.com/nicklockwood/FXLabel
|
13
|
+
//
|
14
|
+
// This software is provided 'as-is', without any express or implied
|
15
|
+
// warranty. In no event will the authors be held liable for any damages
|
16
|
+
// arising from the use of this software.
|
17
|
+
//
|
18
|
+
// Permission is granted to anyone to use this software for any purpose,
|
19
|
+
// including commercial applications, and to alter it and redistribute it
|
20
|
+
// freely, subject to the following restrictions:
|
21
|
+
//
|
22
|
+
// 1. The origin of this software must not be misrepresented; you must not
|
23
|
+
// claim that you wrote the original software. If you use this software
|
24
|
+
// in a product, an acknowledgment in the product documentation would be
|
25
|
+
// appreciated but is not required.
|
26
|
+
//
|
27
|
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
28
|
+
// misrepresented as being the original software.
|
29
|
+
//
|
30
|
+
// 3. This notice may not be removed or altered from any source distribution.
|
31
|
+
//
|
32
|
+
|
33
|
+
|
34
|
+
#import <UIKit/UIKit.h>
|
35
|
+
|
36
|
+
|
37
|
+
@interface NSString (FXLabelDrawing)
|
38
|
+
|
39
|
+
- (CGSize)sizeWithFont:(UIFont *)font
|
40
|
+
minFontSize:(CGFloat)minFontSize
|
41
|
+
actualFontSize:(CGFloat *)actualFontSize
|
42
|
+
forWidth:(CGFloat)width
|
43
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
44
|
+
characterSpacing:(CGFloat)characterSpacing
|
45
|
+
kerningTable:(NSDictionary *)kerningTable;
|
46
|
+
|
47
|
+
- (CGSize)drawAtPoint:(CGPoint)point
|
48
|
+
forWidth:(CGFloat)width
|
49
|
+
withFont:(UIFont *)font
|
50
|
+
minFontSize:(CGFloat)minFontSize
|
51
|
+
actualFontSize:(CGFloat *)actualFontSize
|
52
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
53
|
+
baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment
|
54
|
+
characterSpacing:(CGFloat)characterSpacing
|
55
|
+
kerningTable:(NSDictionary *)kerningTable;
|
56
|
+
|
57
|
+
- (CGSize)sizeWithFont:(UIFont *)font
|
58
|
+
constrainedToSize:(CGSize)size
|
59
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
60
|
+
lineSpacing:(CGFloat)lineSpacing
|
61
|
+
characterSpacing:(CGFloat)characterSpacing
|
62
|
+
kerningTable:(NSDictionary *)kerningTable
|
63
|
+
allowOrphans:(BOOL)allowOrphans;
|
64
|
+
|
65
|
+
- (CGSize)drawInRect:(CGRect)rect
|
66
|
+
withFont:(UIFont *)font
|
67
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
68
|
+
alignment:(NSTextAlignment)alignment
|
69
|
+
lineSpacing:(CGFloat)lineSpacing
|
70
|
+
characterSpacing:(CGFloat)characterSpacing
|
71
|
+
kerningTable:(NSDictionary *)kerningTable
|
72
|
+
allowOrphans:(BOOL)allowOrphans;
|
73
|
+
@end
|
74
|
+
|
75
|
+
|
76
|
+
@interface FXLabel : UILabel
|
77
|
+
|
78
|
+
@property (nonatomic) CGFloat shadowBlur;
|
79
|
+
@property (nonatomic) CGFloat innerShadowBlur;
|
80
|
+
@property (nonatomic) CGSize innerShadowOffset;
|
81
|
+
@property (nonatomic, strong) UIColor *innerShadowColor;
|
82
|
+
@property (nonatomic, strong) UIColor *gradientStartColor;
|
83
|
+
@property (nonatomic, strong) UIColor *gradientEndColor;
|
84
|
+
@property (nonatomic, copy) NSArray *gradientColors;
|
85
|
+
@property (nonatomic) CGPoint gradientStartPoint;
|
86
|
+
@property (nonatomic) CGPoint gradientEndPoint;
|
87
|
+
@property (nonatomic) NSUInteger oversampling;
|
88
|
+
@property (nonatomic) UIEdgeInsets textInsets;
|
89
|
+
@property (nonatomic) CGFloat lineSpacing;
|
90
|
+
@property (nonatomic) CGFloat characterSpacing;
|
91
|
+
@property (nonatomic) CGFloat baselineOffset;
|
92
|
+
@property (nonatomic, copy) NSDictionary *kerningTable;
|
93
|
+
@property (nonatomic) BOOL allowOrphans;
|
94
|
+
|
95
|
+
- (void)setUp;
|
96
|
+
|
97
|
+
@end
|
data/lib/appjam/generators/templates/blank/EiffelApplication/libs/components/FXLabel/FXLabel.m
ADDED
@@ -0,0 +1,1080 @@
|
|
1
|
+
//
|
2
|
+
// FXLabel.m
|
3
|
+
//
|
4
|
+
// Version 1.5 beta
|
5
|
+
//
|
6
|
+
// Created by Nick Lockwood on 20/08/2011.
|
7
|
+
// Copyright 2011 Charcoal Design
|
8
|
+
//
|
9
|
+
// Distributed under the permissive zlib license
|
10
|
+
// Get the latest version from here:
|
11
|
+
//
|
12
|
+
// https://github.com/nicklockwood/FXLabel
|
13
|
+
//
|
14
|
+
// This software is provided 'as-is', without any express or implied
|
15
|
+
// warranty. In no event will the authors be held liable for any damages
|
16
|
+
// arising from the use of this software.
|
17
|
+
//
|
18
|
+
// Permission is granted to anyone to use this software for any purpose,
|
19
|
+
// including commercial applications, and to alter it and redistribute it
|
20
|
+
// freely, subject to the following restrictions:
|
21
|
+
//
|
22
|
+
// 1. The origin of this software must not be misrepresented; you must not
|
23
|
+
// claim that you wrote the original software. If you use this software
|
24
|
+
// in a product, an acknowledgment in the product documentation would be
|
25
|
+
// appreciated but is not required.
|
26
|
+
//
|
27
|
+
// 2. Altered source versions must be plainly marked as such, and must not be
|
28
|
+
// misrepresented as being the original software.
|
29
|
+
//
|
30
|
+
// 3. This notice may not be removed or altered from any source distribution.
|
31
|
+
//
|
32
|
+
|
33
|
+
|
34
|
+
#import "FXLabel.h"
|
35
|
+
|
36
|
+
|
37
|
+
#import <Availability.h>
|
38
|
+
#if !__has_feature(objc_arc)
|
39
|
+
#error This class requires automatic reference counting
|
40
|
+
#endif
|
41
|
+
|
42
|
+
|
43
|
+
@implementation NSString (FXLabelDrawing)
|
44
|
+
|
45
|
+
- (CGContextRef)FXLabel_sizingContext
|
46
|
+
{
|
47
|
+
static CGContextRef context = NULL;
|
48
|
+
if (!context)
|
49
|
+
{
|
50
|
+
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
|
51
|
+
context = CGBitmapContextCreate(NULL, 1, 1, 8, 0, colorSpace, 0);
|
52
|
+
CGContextSetTextDrawingMode(context, kCGTextInvisible);
|
53
|
+
CGColorSpaceRelease(colorSpace);
|
54
|
+
}
|
55
|
+
return context;
|
56
|
+
}
|
57
|
+
|
58
|
+
- (BOOL)FXLabel_isPunctuation
|
59
|
+
{
|
60
|
+
return [[NSSet setWithObjects:
|
61
|
+
@"-", //hyphen
|
62
|
+
@"–", //en-dash
|
63
|
+
@"—", //em-dash
|
64
|
+
@";",
|
65
|
+
nil] containsObject:self];
|
66
|
+
}
|
67
|
+
|
68
|
+
- (NSArray *)FXLabel_characters
|
69
|
+
{
|
70
|
+
NSUInteger length = [self length];
|
71
|
+
NSMutableArray *characters = [NSMutableArray arrayWithCapacity:length];
|
72
|
+
for (NSUInteger i = 0; i < length; i++)
|
73
|
+
{
|
74
|
+
NSRange range = [self rangeOfComposedCharacterSequenceAtIndex:i];
|
75
|
+
[characters addObject:[self substringWithRange:range]];
|
76
|
+
i += range.length - 1;
|
77
|
+
}
|
78
|
+
return characters;
|
79
|
+
}
|
80
|
+
|
81
|
+
- (NSArray *)FXLabel_linesWithFont:(UIFont *)font
|
82
|
+
constrainedToSize:(CGSize)size
|
83
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
84
|
+
lineSpacing:(CGFloat)lineSpacing
|
85
|
+
characterSpacing:(CGFloat)characterSpacing
|
86
|
+
kerningTable:(NSDictionary *)kerningTable
|
87
|
+
allowOrphans:(BOOL)allowOrphans
|
88
|
+
{
|
89
|
+
NSInteger index = 0;
|
90
|
+
NSMutableArray *lines = [NSMutableArray array];
|
91
|
+
if (lineBreakMode == NSLineBreakByCharWrapping)
|
92
|
+
{
|
93
|
+
//split text into individual characters
|
94
|
+
NSArray *characters = [self FXLabel_characters];
|
95
|
+
|
96
|
+
//calculate lines
|
97
|
+
while (index < [characters count])
|
98
|
+
{
|
99
|
+
NSInteger lineCount = [lines count];
|
100
|
+
if (lineCount && ((lineCount + 1) * font.lineHeight + lineCount * font.pointSize * lineSpacing) > size.height)
|
101
|
+
{
|
102
|
+
//append remaining text to last line
|
103
|
+
NSArray *remainingChars = [characters subarrayWithRange:NSMakeRange(index, [characters count] - index)];
|
104
|
+
NSString *line = [lines lastObject];
|
105
|
+
NSString *newLine = [line length]? line: @"";
|
106
|
+
newLine = [newLine stringByAppendingString:[remainingChars componentsJoinedByString:@""]];
|
107
|
+
[lines replaceObjectAtIndex:lineCount - 1 withObject:newLine];
|
108
|
+
break;
|
109
|
+
}
|
110
|
+
NSString *line = nil;
|
111
|
+
for (int i = index; i < [characters count]; i++)
|
112
|
+
{
|
113
|
+
NSString *character = characters[i];
|
114
|
+
NSString *newLine = line? [line stringByAppendingString:character]: character;
|
115
|
+
CGFloat lineWidth = [newLine sizeWithFont:font
|
116
|
+
minFontSize:font.pointSize
|
117
|
+
actualFontSize:NULL
|
118
|
+
forWidth:INFINITY
|
119
|
+
lineBreakMode:lineBreakMode
|
120
|
+
characterSpacing:characterSpacing
|
121
|
+
kerningTable:kerningTable].width;
|
122
|
+
|
123
|
+
if ([character isEqualToString:@"\n"])
|
124
|
+
{
|
125
|
+
//add line and prepare for next
|
126
|
+
[lines addObject:line ?: @""];
|
127
|
+
index = i + 1;
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
else if (lineWidth > size.width && line)
|
131
|
+
{
|
132
|
+
//add line and prepare for next
|
133
|
+
[lines addObject:line];
|
134
|
+
index = i;
|
135
|
+
break;
|
136
|
+
}
|
137
|
+
else if (i == [characters count] - 1)
|
138
|
+
{
|
139
|
+
//add line and finish
|
140
|
+
[lines addObject:newLine];
|
141
|
+
index = i + 1;
|
142
|
+
break;
|
143
|
+
}
|
144
|
+
else
|
145
|
+
{
|
146
|
+
//continue
|
147
|
+
line = newLine;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
else
|
153
|
+
{
|
154
|
+
//split text into words
|
155
|
+
NSString *text = [self stringByReplacingOccurrencesOfString:@"\t" withString:@" "];
|
156
|
+
text = [text stringByReplacingOccurrencesOfString:@"\n" withString:@" \n "];
|
157
|
+
NSArray *words = [text componentsSeparatedByString:@" "];
|
158
|
+
words = [words filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"length > 0"]];
|
159
|
+
|
160
|
+
//calculate lines
|
161
|
+
while (index < [words count])
|
162
|
+
{
|
163
|
+
NSInteger lineCount = [lines count];
|
164
|
+
if (lineCount && ((lineCount + 1) * font.lineHeight + lineCount * font.pointSize * lineSpacing) > size.height)
|
165
|
+
{
|
166
|
+
//append remaining text to last line
|
167
|
+
NSArray *remainingWords = [words subarrayWithRange:NSMakeRange(index, [words count] - index)];
|
168
|
+
NSString *line = [lines lastObject];
|
169
|
+
NSString *newLine = [line length]? [line stringByAppendingString:@" "]: @"";
|
170
|
+
newLine = [newLine stringByAppendingString:[remainingWords componentsJoinedByString:@" "]];
|
171
|
+
newLine = [newLine stringByReplacingOccurrencesOfString:@"\n " withString:@"\n"];
|
172
|
+
newLine = [newLine stringByReplacingOccurrencesOfString:@" \n" withString:@"\n"];
|
173
|
+
[lines replaceObjectAtIndex:lineCount - 1 withObject:newLine];
|
174
|
+
break;
|
175
|
+
}
|
176
|
+
NSString *line = nil;
|
177
|
+
for (int i = index; i < [words count]; i++)
|
178
|
+
{
|
179
|
+
NSString *word = words[i];
|
180
|
+
NSString *newLine = line? [line stringByAppendingFormat:@" %@", word]: word;
|
181
|
+
CGFloat lineWidth = [newLine sizeWithFont:font
|
182
|
+
minFontSize:font.pointSize
|
183
|
+
actualFontSize:NULL
|
184
|
+
forWidth:INFINITY
|
185
|
+
lineBreakMode:lineBreakMode
|
186
|
+
characterSpacing:characterSpacing
|
187
|
+
kerningTable:kerningTable].width;
|
188
|
+
|
189
|
+
if ([word isEqualToString:@"\n"])
|
190
|
+
{
|
191
|
+
//add line and prepare for next
|
192
|
+
[lines addObject:line ?: @""];
|
193
|
+
index = i + 1;
|
194
|
+
break;
|
195
|
+
}
|
196
|
+
else if (lineWidth > size.width && line)
|
197
|
+
{
|
198
|
+
//check for orphans
|
199
|
+
if (!allowOrphans && i > 0 &&
|
200
|
+
(i == [words count] - 1 || [words[i + 1] isEqualToString:@"\n"]) &&
|
201
|
+
![words[i - 1] FXLabel_isPunctuation])
|
202
|
+
{
|
203
|
+
//force line break
|
204
|
+
NSRange range = [line rangeOfString:@" " options:NSBackwardsSearch];
|
205
|
+
if (range.location != NSNotFound)
|
206
|
+
{
|
207
|
+
line = [line substringToIndex:range.location];
|
208
|
+
i --;
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
//add line and prepare for next
|
213
|
+
[lines addObject:line];
|
214
|
+
index = i;
|
215
|
+
break;
|
216
|
+
}
|
217
|
+
else if (i == [words count] - 1)
|
218
|
+
{
|
219
|
+
//add line and finish
|
220
|
+
[lines addObject:newLine];
|
221
|
+
index = i + 1;
|
222
|
+
break;
|
223
|
+
}
|
224
|
+
else
|
225
|
+
{
|
226
|
+
//continue
|
227
|
+
line = newLine;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
return lines;
|
233
|
+
}
|
234
|
+
|
235
|
+
- (CGSize)FXLabel_sizeWithFont:(UIFont *)font
|
236
|
+
minFontSize:(CGFloat)minFontSize
|
237
|
+
actualFontSize:(CGFloat *)actualFontSize
|
238
|
+
forWidth:(CGFloat)width
|
239
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
240
|
+
characterSpacing:(CGFloat)characterSpacing
|
241
|
+
kerningTable:(NSDictionary *)kerningTable
|
242
|
+
charactersFitted:(NSInteger *)charactersFitted
|
243
|
+
includesEllipsis:(BOOL *)includesEllipsis
|
244
|
+
{
|
245
|
+
UIGraphicsPushContext([self FXLabel_sizingContext]);
|
246
|
+
|
247
|
+
if (includesEllipsis) *includesEllipsis = NO;
|
248
|
+
minFontSize = minFontSize ?: font.pointSize;
|
249
|
+
UIFont *subFont = font;
|
250
|
+
while (true)
|
251
|
+
{
|
252
|
+
//TODO: doesn't correctly handle head or center truncation
|
253
|
+
|
254
|
+
int i = 0;
|
255
|
+
CGFloat x = 0.0f;
|
256
|
+
NSArray *characters = [self FXLabel_characters];
|
257
|
+
NSInteger charCount = [characters count];
|
258
|
+
NSMutableArray *widths = [NSMutableArray arrayWithCapacity:charCount];
|
259
|
+
for (i = 0; i < [characters count]; i++)
|
260
|
+
{
|
261
|
+
//get character width
|
262
|
+
NSString *character = characters[i];
|
263
|
+
CGFloat charWidth = [character drawAtPoint:CGPointZero withFont:subFont].width;
|
264
|
+
if (i == charCount - 1 || x + charWidth > width)
|
265
|
+
{
|
266
|
+
[widths addObject:@(charWidth)];
|
267
|
+
x += charWidth;
|
268
|
+
break;
|
269
|
+
}
|
270
|
+
else
|
271
|
+
{
|
272
|
+
charWidth += ([kerningTable[character] floatValue] + characterSpacing) * subFont.pointSize;
|
273
|
+
[widths addObject:@(charWidth)];
|
274
|
+
x += charWidth;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
if (floorf(x) <= ceilf(width))
|
278
|
+
{
|
279
|
+
//the text fits, return size
|
280
|
+
UIGraphicsPopContext();
|
281
|
+
if (actualFontSize) *actualFontSize = subFont.pointSize;
|
282
|
+
if (charactersFitted) *charactersFitted = charCount;
|
283
|
+
return CGSizeMake(x, font.lineHeight);
|
284
|
+
}
|
285
|
+
else if (subFont.pointSize == minFontSize)
|
286
|
+
{
|
287
|
+
//text is truncated
|
288
|
+
if (lineBreakMode == NSLineBreakByClipping)
|
289
|
+
{
|
290
|
+
//subtract width of last character
|
291
|
+
x -= [[widths lastObject] floatValue];
|
292
|
+
|
293
|
+
UIGraphicsPopContext();
|
294
|
+
if (actualFontSize) *actualFontSize = subFont.pointSize;
|
295
|
+
if (charactersFitted) *charactersFitted = i + 1;
|
296
|
+
return CGSizeMake(x, font.lineHeight);
|
297
|
+
}
|
298
|
+
else
|
299
|
+
{
|
300
|
+
//allow space for ellipsis
|
301
|
+
CGFloat ellipsisWidth = [@"…" sizeWithFont:subFont].width;
|
302
|
+
if (ellipsisWidth > width)
|
303
|
+
{
|
304
|
+
//can't fit any text at all
|
305
|
+
UIGraphicsPopContext();
|
306
|
+
if (actualFontSize) *actualFontSize = subFont.pointSize;
|
307
|
+
if (charactersFitted) *charactersFitted = 0;
|
308
|
+
return CGSizeMake(0.0f, font.lineHeight);
|
309
|
+
}
|
310
|
+
else
|
311
|
+
{
|
312
|
+
//remove enough characters to allow space for ellipsis
|
313
|
+
for (i = [widths count] - 1; i >= 0; i--)
|
314
|
+
{
|
315
|
+
x -= [widths[i] floatValue];
|
316
|
+
if (x + ellipsisWidth <= width) break;
|
317
|
+
}
|
318
|
+
UIGraphicsPopContext();
|
319
|
+
if (actualFontSize) *actualFontSize = subFont.pointSize;
|
320
|
+
if (charactersFitted) *charactersFitted = MAX(0, i);
|
321
|
+
if (includesEllipsis) *includesEllipsis = YES;
|
322
|
+
return CGSizeMake(x + ellipsisWidth, font.lineHeight);
|
323
|
+
}
|
324
|
+
}
|
325
|
+
}
|
326
|
+
else
|
327
|
+
{
|
328
|
+
//try again with the next point size
|
329
|
+
CGFloat pointSize = MAX(minFontSize, subFont.pointSize - 1.0f);
|
330
|
+
subFont = [font fontWithSize:pointSize];
|
331
|
+
}
|
332
|
+
}
|
333
|
+
}
|
334
|
+
|
335
|
+
- (CGSize)sizeWithFont:(UIFont *)font
|
336
|
+
minFontSize:(CGFloat)minFontSize
|
337
|
+
actualFontSize:(CGFloat *)actualFontSize
|
338
|
+
forWidth:(CGFloat)width
|
339
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
340
|
+
characterSpacing:(CGFloat)characterSpacing
|
341
|
+
kerningTable:(NSDictionary *)kerningTable
|
342
|
+
{
|
343
|
+
if (characterSpacing || [kerningTable count])
|
344
|
+
{
|
345
|
+
CGSize size = [self FXLabel_sizeWithFont:font
|
346
|
+
minFontSize:minFontSize
|
347
|
+
actualFontSize:actualFontSize
|
348
|
+
forWidth:width
|
349
|
+
lineBreakMode:lineBreakMode
|
350
|
+
characterSpacing:characterSpacing
|
351
|
+
kerningTable:kerningTable
|
352
|
+
charactersFitted:NULL
|
353
|
+
includesEllipsis:NULL];
|
354
|
+
|
355
|
+
//round up size to nearest point like normal NSString size functions do
|
356
|
+
return CGSizeMake(ceilf(size.width), ceilf(size.height));
|
357
|
+
}
|
358
|
+
else
|
359
|
+
{
|
360
|
+
//use standard implementation
|
361
|
+
return [self sizeWithFont:font
|
362
|
+
minFontSize:minFontSize
|
363
|
+
actualFontSize:actualFontSize
|
364
|
+
forWidth:width
|
365
|
+
lineBreakMode:lineBreakMode];
|
366
|
+
}
|
367
|
+
}
|
368
|
+
|
369
|
+
- (CGSize)drawAtPoint:(CGPoint)point
|
370
|
+
forWidth:(CGFloat)width
|
371
|
+
withFont:(UIFont *)font
|
372
|
+
minFontSize:(CGFloat)minFontSize
|
373
|
+
actualFontSize:(CGFloat *)actualFontSize
|
374
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
375
|
+
baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment
|
376
|
+
characterSpacing:(CGFloat)characterSpacing
|
377
|
+
kerningTable:(NSDictionary *)kerningTable
|
378
|
+
{
|
379
|
+
if (characterSpacing || [kerningTable count])
|
380
|
+
{
|
381
|
+
//TODO: draw text to image and then paste into context to avoid overlap issues
|
382
|
+
//TODO: doesn't correctly handle head or center truncation
|
383
|
+
|
384
|
+
NSInteger charactersFitted = 0;
|
385
|
+
BOOL includesEllipsis = NO;
|
386
|
+
CGFloat fontSize = font.pointSize;
|
387
|
+
CGSize size = [self FXLabel_sizeWithFont:font
|
388
|
+
minFontSize:minFontSize
|
389
|
+
actualFontSize:&fontSize
|
390
|
+
forWidth:width
|
391
|
+
lineBreakMode:lineBreakMode
|
392
|
+
characterSpacing:characterSpacing
|
393
|
+
kerningTable:kerningTable
|
394
|
+
charactersFitted:&charactersFitted
|
395
|
+
includesEllipsis:&includesEllipsis];
|
396
|
+
|
397
|
+
CGFloat y = point.y;
|
398
|
+
UIFont *subFont = [font fontWithSize:fontSize];
|
399
|
+
if (fontSize < font.pointSize)
|
400
|
+
{
|
401
|
+
switch (baselineAdjustment)
|
402
|
+
{
|
403
|
+
case UIBaselineAdjustmentAlignCenters:
|
404
|
+
{
|
405
|
+
y += (font.lineHeight - subFont.lineHeight) / 2.0f;
|
406
|
+
break;
|
407
|
+
}
|
408
|
+
case UIBaselineAdjustmentAlignBaselines:
|
409
|
+
{
|
410
|
+
y += (font.ascender - subFont.ascender);
|
411
|
+
break;
|
412
|
+
}
|
413
|
+
case UIBaselineAdjustmentNone:
|
414
|
+
default:
|
415
|
+
{
|
416
|
+
//no adjustment needed
|
417
|
+
break;
|
418
|
+
}
|
419
|
+
}
|
420
|
+
}
|
421
|
+
|
422
|
+
CGFloat x = point.x;
|
423
|
+
for (int i = 0; i < charactersFitted; i++)
|
424
|
+
{
|
425
|
+
NSString *character = [self substringWithRange:NSMakeRange(i, 1)];
|
426
|
+
CGFloat charWidth = [character drawAtPoint:CGPointMake(x, y) withFont:subFont].width;
|
427
|
+
x += charWidth + ([kerningTable[character] floatValue] + characterSpacing) * subFont.pointSize;
|
428
|
+
}
|
429
|
+
if (includesEllipsis)
|
430
|
+
{
|
431
|
+
[@"…" drawAtPoint:CGPointMake(x, point.y) withFont:subFont];
|
432
|
+
}
|
433
|
+
|
434
|
+
if (actualFontSize) *actualFontSize = fontSize;
|
435
|
+
return size;
|
436
|
+
}
|
437
|
+
else
|
438
|
+
{
|
439
|
+
//use standard implementation
|
440
|
+
return [self drawAtPoint:point
|
441
|
+
forWidth:width
|
442
|
+
withFont:font
|
443
|
+
minFontSize:minFontSize
|
444
|
+
actualFontSize:actualFontSize
|
445
|
+
lineBreakMode:lineBreakMode
|
446
|
+
baselineAdjustment:baselineAdjustment];
|
447
|
+
}
|
448
|
+
}
|
449
|
+
|
450
|
+
- (CGSize)sizeWithFont:(UIFont *)font
|
451
|
+
constrainedToSize:(CGSize)size
|
452
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
453
|
+
lineSpacing:(CGFloat)lineSpacing
|
454
|
+
characterSpacing:(CGFloat)characterSpacing
|
455
|
+
kerningTable:(NSDictionary *)kerningTable
|
456
|
+
allowOrphans:(BOOL)allowOrphans
|
457
|
+
{
|
458
|
+
if (lineSpacing || characterSpacing || [kerningTable count] || !allowOrphans)
|
459
|
+
{
|
460
|
+
NSArray *lines = [self FXLabel_linesWithFont:font
|
461
|
+
constrainedToSize:size
|
462
|
+
lineBreakMode:lineBreakMode
|
463
|
+
lineSpacing:lineSpacing
|
464
|
+
characterSpacing:characterSpacing
|
465
|
+
kerningTable:kerningTable
|
466
|
+
allowOrphans:allowOrphans];
|
467
|
+
CGSize total = CGSizeZero;
|
468
|
+
total.height = ceilf(MIN(size.height, [lines count] * font.lineHeight + ([lines count] - 1) * roundf(font.pointSize *lineSpacing)));
|
469
|
+
for (NSString *line in lines)
|
470
|
+
{
|
471
|
+
total.width = ceilf(MAX(total.width, [line sizeWithFont:font
|
472
|
+
minFontSize:font.pointSize
|
473
|
+
actualFontSize:NULL
|
474
|
+
forWidth:size.width
|
475
|
+
lineBreakMode:lineBreakMode
|
476
|
+
characterSpacing:characterSpacing
|
477
|
+
kerningTable:kerningTable].width));
|
478
|
+
}
|
479
|
+
return total;
|
480
|
+
}
|
481
|
+
else
|
482
|
+
{
|
483
|
+
//use standard implementation
|
484
|
+
return [self sizeWithFont:font
|
485
|
+
constrainedToSize:size
|
486
|
+
lineBreakMode:lineBreakMode];
|
487
|
+
}
|
488
|
+
}
|
489
|
+
|
490
|
+
- (CGSize)drawInRect:(CGRect)rect
|
491
|
+
withFont:(UIFont *)font
|
492
|
+
lineBreakMode:(NSLineBreakMode)lineBreakMode
|
493
|
+
alignment:(NSTextAlignment)alignment
|
494
|
+
lineSpacing:(CGFloat)lineSpacing
|
495
|
+
characterSpacing:(CGFloat)characterSpacing
|
496
|
+
kerningTable:(NSDictionary *)kerningTable
|
497
|
+
allowOrphans:(BOOL)allowOrphans
|
498
|
+
{
|
499
|
+
if (lineSpacing || characterSpacing || [kerningTable count] || !allowOrphans)
|
500
|
+
{
|
501
|
+
//TODO: draw text to image and then paste into context to avoid overlap issues
|
502
|
+
|
503
|
+
NSArray *lines = [self FXLabel_linesWithFont:font
|
504
|
+
constrainedToSize:rect.size
|
505
|
+
lineBreakMode:lineBreakMode
|
506
|
+
lineSpacing:lineSpacing
|
507
|
+
characterSpacing:characterSpacing
|
508
|
+
kerningTable:kerningTable
|
509
|
+
allowOrphans:allowOrphans];
|
510
|
+
CGSize total = CGSizeZero;
|
511
|
+
total.height = [lines count] * font.lineHeight + ([lines count] - 1) * roundf(font.pointSize * lineSpacing);
|
512
|
+
CGPoint offset = rect.origin;
|
513
|
+
for (NSString *line in lines)
|
514
|
+
{
|
515
|
+
CGSize size = [line sizeWithFont:font
|
516
|
+
minFontSize:font.pointSize
|
517
|
+
actualFontSize:NULL
|
518
|
+
forWidth:CGRectGetWidth(rect)
|
519
|
+
lineBreakMode:lineBreakMode
|
520
|
+
characterSpacing:characterSpacing
|
521
|
+
kerningTable:kerningTable];
|
522
|
+
|
523
|
+
if (alignment == NSTextAlignmentCenter)
|
524
|
+
{
|
525
|
+
offset.x = roundf(rect.origin.x + (CGRectGetWidth(rect) - size.width)/ 2.0f);
|
526
|
+
}
|
527
|
+
else if (alignment == NSTextAlignmentRight)
|
528
|
+
{
|
529
|
+
offset.x = roundf(rect.origin.x + (CGRectGetWidth(rect) - size.width));
|
530
|
+
}
|
531
|
+
[line drawAtPoint:offset
|
532
|
+
forWidth:CGRectGetWidth(rect)
|
533
|
+
withFont:font
|
534
|
+
minFontSize:font.pointSize
|
535
|
+
actualFontSize:NULL
|
536
|
+
lineBreakMode:lineBreakMode
|
537
|
+
baselineAdjustment:UIBaselineAdjustmentAlignBaselines
|
538
|
+
characterSpacing:characterSpacing
|
539
|
+
kerningTable:kerningTable];
|
540
|
+
|
541
|
+
total.width = MAX(total.width, offset.x + size.width);
|
542
|
+
offset.y += roundf(font.lineHeight + font.pointSize * lineSpacing);
|
543
|
+
}
|
544
|
+
return total;
|
545
|
+
}
|
546
|
+
else
|
547
|
+
{
|
548
|
+
//use standard implementation
|
549
|
+
return [self drawInRect:rect
|
550
|
+
withFont:font
|
551
|
+
lineBreakMode:lineBreakMode
|
552
|
+
alignment:alignment];
|
553
|
+
}
|
554
|
+
}
|
555
|
+
|
556
|
+
@end
|
557
|
+
|
558
|
+
|
559
|
+
@interface FXLabel ()
|
560
|
+
|
561
|
+
@property (nonatomic, assign) NSUInteger minSamples;
|
562
|
+
@property (nonatomic, assign) NSUInteger maxSamples;
|
563
|
+
|
564
|
+
@end
|
565
|
+
|
566
|
+
|
567
|
+
@implementation FXLabel
|
568
|
+
|
569
|
+
@synthesize shadowBlur; //no leading _ to avoid conflict with private property
|
570
|
+
|
571
|
+
- (void)setUp
|
572
|
+
{
|
573
|
+
_gradientStartPoint = CGPointMake(0.5f, 0.0f);
|
574
|
+
_gradientEndPoint = CGPointMake(0.5f, 0.75f);
|
575
|
+
_minSamples = _maxSamples = 1;
|
576
|
+
if ([UIScreen instancesRespondToSelector:@selector(scale)])
|
577
|
+
{
|
578
|
+
_minSamples = [UIScreen mainScreen].scale;
|
579
|
+
_maxSamples = 32;
|
580
|
+
}
|
581
|
+
_oversampling = _minSamples;
|
582
|
+
_allowOrphans = YES;
|
583
|
+
}
|
584
|
+
|
585
|
+
- (id)initWithFrame:(CGRect)frame
|
586
|
+
{
|
587
|
+
if ((self = [super initWithFrame:frame]))
|
588
|
+
{
|
589
|
+
self.backgroundColor = nil;
|
590
|
+
[self setUp];
|
591
|
+
}
|
592
|
+
return self;
|
593
|
+
}
|
594
|
+
|
595
|
+
- (id)initWithCoder:(NSCoder *)aDecoder
|
596
|
+
{
|
597
|
+
if ((self = [super initWithCoder:aDecoder]))
|
598
|
+
{
|
599
|
+
[self setUp];
|
600
|
+
}
|
601
|
+
return self;
|
602
|
+
}
|
603
|
+
|
604
|
+
- (void)setShadowBlur:(CGFloat)blur
|
605
|
+
{
|
606
|
+
if (shadowBlur != blur)
|
607
|
+
{
|
608
|
+
shadowBlur = blur;
|
609
|
+
[self setNeedsDisplay];
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
- (void)setInnerShadowBlur:(CGFloat)blur
|
614
|
+
{
|
615
|
+
if (_innerShadowBlur != blur)
|
616
|
+
{
|
617
|
+
_innerShadowBlur = blur;
|
618
|
+
[self setNeedsDisplay];
|
619
|
+
}
|
620
|
+
}
|
621
|
+
|
622
|
+
- (void)setInnerShadowOffset:(CGSize)offset
|
623
|
+
{
|
624
|
+
if (!CGSizeEqualToSize(_innerShadowOffset, offset))
|
625
|
+
{
|
626
|
+
_innerShadowOffset = offset;
|
627
|
+
[self setNeedsDisplay];
|
628
|
+
}
|
629
|
+
}
|
630
|
+
|
631
|
+
- (void)setInnerShadowColor:(UIColor *)color
|
632
|
+
{
|
633
|
+
if (_innerShadowColor != color)
|
634
|
+
{
|
635
|
+
_innerShadowColor = color;
|
636
|
+
[self setNeedsDisplay];
|
637
|
+
}
|
638
|
+
}
|
639
|
+
|
640
|
+
- (UIColor *)gradientStartColor
|
641
|
+
{
|
642
|
+
return [_gradientColors count]? _gradientColors[0]: nil;
|
643
|
+
}
|
644
|
+
|
645
|
+
- (void)setGradientStartColor:(UIColor *)color
|
646
|
+
{
|
647
|
+
if (color == nil)
|
648
|
+
{
|
649
|
+
self.gradientColors = nil;
|
650
|
+
}
|
651
|
+
else if ([_gradientColors count] < 2)
|
652
|
+
{
|
653
|
+
self.gradientColors = @[color, color];
|
654
|
+
}
|
655
|
+
else if (_gradientColors[0] != color)
|
656
|
+
{
|
657
|
+
NSMutableArray *colors = [NSMutableArray arrayWithArray:_gradientColors];
|
658
|
+
colors[0] = color;
|
659
|
+
self.gradientColors = colors;
|
660
|
+
}
|
661
|
+
}
|
662
|
+
|
663
|
+
- (UIColor *)gradientEndColor
|
664
|
+
{
|
665
|
+
return [_gradientColors lastObject];
|
666
|
+
}
|
667
|
+
|
668
|
+
- (void)setGradientEndColor:(UIColor *)color
|
669
|
+
{
|
670
|
+
if (color == nil)
|
671
|
+
{
|
672
|
+
self.gradientColors = nil;
|
673
|
+
}
|
674
|
+
else if ([_gradientColors count] < 2)
|
675
|
+
{
|
676
|
+
self.gradientColors = @[color, color];
|
677
|
+
}
|
678
|
+
else if ([_gradientColors lastObject] != color)
|
679
|
+
{
|
680
|
+
NSMutableArray *colors = [NSMutableArray arrayWithArray:_gradientColors];
|
681
|
+
colors[[colors count] - 1] = color;
|
682
|
+
self.gradientColors = colors;
|
683
|
+
}
|
684
|
+
}
|
685
|
+
|
686
|
+
- (void)setGradientColors:(NSArray *)colors
|
687
|
+
{
|
688
|
+
if (_gradientColors != colors)
|
689
|
+
{
|
690
|
+
_gradientColors = [colors copy];
|
691
|
+
[self setNeedsDisplay];
|
692
|
+
}
|
693
|
+
}
|
694
|
+
|
695
|
+
- (void)setOversampling:(NSUInteger)samples
|
696
|
+
{
|
697
|
+
samples = MIN(_maxSamples, MAX(_minSamples, samples));
|
698
|
+
if (_oversampling != samples)
|
699
|
+
{
|
700
|
+
_oversampling = samples;
|
701
|
+
[self setNeedsDisplay];
|
702
|
+
}
|
703
|
+
}
|
704
|
+
|
705
|
+
- (void)setTextInsets:(UIEdgeInsets)insets
|
706
|
+
{
|
707
|
+
if (!UIEdgeInsetsEqualToEdgeInsets(_textInsets, insets))
|
708
|
+
{
|
709
|
+
_textInsets = insets;
|
710
|
+
[self setNeedsDisplay];
|
711
|
+
}
|
712
|
+
}
|
713
|
+
|
714
|
+
- (void)setLineSpacing:(CGFloat)lineSpacing
|
715
|
+
{
|
716
|
+
if (_lineSpacing != lineSpacing)
|
717
|
+
{
|
718
|
+
_lineSpacing = lineSpacing;
|
719
|
+
[self setNeedsDisplay];
|
720
|
+
}
|
721
|
+
}
|
722
|
+
|
723
|
+
- (void)setCharacterSpacing:(CGFloat)characterSpacing
|
724
|
+
{
|
725
|
+
if (_characterSpacing != characterSpacing)
|
726
|
+
{
|
727
|
+
_characterSpacing = characterSpacing;
|
728
|
+
[self setNeedsDisplay];
|
729
|
+
}
|
730
|
+
}
|
731
|
+
|
732
|
+
- (void)setBaselineOffset:(CGFloat)baselineOffset
|
733
|
+
{
|
734
|
+
if (_baselineOffset != baselineOffset)
|
735
|
+
{
|
736
|
+
_baselineOffset = baselineOffset;
|
737
|
+
[self setNeedsDisplay];
|
738
|
+
}
|
739
|
+
}
|
740
|
+
|
741
|
+
- (void)setCharacterKerning:(NSDictionary *)kerningTable
|
742
|
+
{
|
743
|
+
if (_kerningTable != kerningTable)
|
744
|
+
{
|
745
|
+
_kerningTable = [kerningTable copy];
|
746
|
+
[self setNeedsDisplay];
|
747
|
+
}
|
748
|
+
}
|
749
|
+
|
750
|
+
- (void)setAllowOrphans:(BOOL)allowOrphans
|
751
|
+
{
|
752
|
+
if (_allowOrphans != allowOrphans)
|
753
|
+
{
|
754
|
+
_allowOrphans = allowOrphans;
|
755
|
+
[self setNeedsDisplay];
|
756
|
+
}
|
757
|
+
}
|
758
|
+
|
759
|
+
- (CGSize)FXLabel_sizeThatFits:(CGSize)size actualFontSize:(CGFloat *)actualFontSize
|
760
|
+
{
|
761
|
+
size.width = size.width ?: INFINITY;
|
762
|
+
size.height = size.height ?: INFINITY;
|
763
|
+
|
764
|
+
if (self.numberOfLines == 1)
|
765
|
+
{
|
766
|
+
|
767
|
+
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
|
768
|
+
|
769
|
+
CGFloat minimumFontSize = self.minimumFontSize ?: self.font.pointSize;
|
770
|
+
|
771
|
+
#else
|
772
|
+
|
773
|
+
CGFloat minimumFontSize = self.minimumScaleFactor? self.minimumScaleFactor * self.font.pointSize: self.font.pointSize;
|
774
|
+
|
775
|
+
#endif
|
776
|
+
size = [self.text sizeWithFont:self.font
|
777
|
+
minFontSize:minimumFontSize
|
778
|
+
actualFontSize:actualFontSize
|
779
|
+
forWidth:size.width
|
780
|
+
lineBreakMode:self.lineBreakMode
|
781
|
+
characterSpacing:_characterSpacing
|
782
|
+
kerningTable:_kerningTable];
|
783
|
+
}
|
784
|
+
else
|
785
|
+
{
|
786
|
+
if (actualFontSize)
|
787
|
+
{
|
788
|
+
*actualFontSize = self.font.pointSize;
|
789
|
+
}
|
790
|
+
size = [self.text sizeWithFont:self.font
|
791
|
+
constrainedToSize:size
|
792
|
+
lineBreakMode:self.lineBreakMode
|
793
|
+
lineSpacing:_lineSpacing
|
794
|
+
characterSpacing:_characterSpacing
|
795
|
+
kerningTable:_kerningTable
|
796
|
+
allowOrphans:_allowOrphans];
|
797
|
+
|
798
|
+
if (self.numberOfLines > 0)
|
799
|
+
{
|
800
|
+
size.height = MIN(size.height, self.numberOfLines * self.font.lineHeight + (self.numberOfLines - 1) * self.font.pointSize * _lineSpacing);
|
801
|
+
}
|
802
|
+
}
|
803
|
+
return size;
|
804
|
+
}
|
805
|
+
|
806
|
+
- (CGSize)sizeThatFits:(CGSize)size
|
807
|
+
{
|
808
|
+
size.width -= (_textInsets.left + _textInsets.right);
|
809
|
+
size.height -= (_textInsets.top + _textInsets.bottom);
|
810
|
+
size = [self FXLabel_sizeThatFits:size actualFontSize:NULL];
|
811
|
+
size.width += (_textInsets.left + _textInsets.right);
|
812
|
+
size.height += (_textInsets.top + _textInsets.bottom);
|
813
|
+
return size;
|
814
|
+
}
|
815
|
+
|
816
|
+
- (void)FXLabel_getComponents:(CGFloat *)rgba forColor:(CGColorRef)color
|
817
|
+
{
|
818
|
+
CGColorSpaceModel model = CGColorSpaceGetModel(CGColorGetColorSpace(color));
|
819
|
+
const CGFloat *components = CGColorGetComponents(color);
|
820
|
+
switch (model)
|
821
|
+
{
|
822
|
+
case kCGColorSpaceModelMonochrome:
|
823
|
+
{
|
824
|
+
rgba[0] = components[0];
|
825
|
+
rgba[1] = components[0];
|
826
|
+
rgba[2] = components[0];
|
827
|
+
rgba[3] = components[1];
|
828
|
+
break;
|
829
|
+
}
|
830
|
+
case kCGColorSpaceModelRGB:
|
831
|
+
{
|
832
|
+
rgba[0] = components[0];
|
833
|
+
rgba[1] = components[1];
|
834
|
+
rgba[2] = components[2];
|
835
|
+
rgba[3] = components[3];
|
836
|
+
break;
|
837
|
+
}
|
838
|
+
default:
|
839
|
+
{
|
840
|
+
NSLog(@"Unsupported gradient color format: %i", model);
|
841
|
+
rgba[0] = 0.0f;
|
842
|
+
rgba[1] = 0.0f;
|
843
|
+
rgba[2] = 0.0f;
|
844
|
+
rgba[3] = 1.0f;
|
845
|
+
break;
|
846
|
+
}
|
847
|
+
}
|
848
|
+
}
|
849
|
+
|
850
|
+
- (UIColor *)FXLabel_color:(CGColorRef)a blendedWithColor:(CGColorRef)b
|
851
|
+
{
|
852
|
+
CGFloat aRGBA[4];
|
853
|
+
[self FXLabel_getComponents:aRGBA forColor:a];
|
854
|
+
CGFloat bRGBA[4];
|
855
|
+
[self FXLabel_getComponents:bRGBA forColor:b];
|
856
|
+
CGFloat source = aRGBA[3];
|
857
|
+
CGFloat dest = 1.0f - source;
|
858
|
+
return [UIColor colorWithRed:source * aRGBA[0] + dest * bRGBA[0]
|
859
|
+
green:source * aRGBA[1] + dest * bRGBA[1]
|
860
|
+
blue:source * aRGBA[2] + dest * bRGBA[2]
|
861
|
+
alpha:bRGBA[3] + (1.0f - bRGBA[3]) * aRGBA[3]];
|
862
|
+
}
|
863
|
+
|
864
|
+
- (void)FXLabel_drawTextInRect:(CGRect)rect withFont:(UIFont *)font
|
865
|
+
{
|
866
|
+
rect.origin.y += font.pointSize * _baselineOffset;
|
867
|
+
if (self.numberOfLines == 1)
|
868
|
+
{
|
869
|
+
[self.text drawAtPoint:rect.origin
|
870
|
+
forWidth:rect.size.width
|
871
|
+
withFont:self.font
|
872
|
+
minFontSize:font.pointSize
|
873
|
+
actualFontSize:NULL
|
874
|
+
lineBreakMode:self.lineBreakMode
|
875
|
+
baselineAdjustment:self.baselineAdjustment
|
876
|
+
characterSpacing:_characterSpacing
|
877
|
+
kerningTable:_kerningTable];
|
878
|
+
}
|
879
|
+
else
|
880
|
+
{
|
881
|
+
[self.text drawInRect:rect
|
882
|
+
withFont:font
|
883
|
+
lineBreakMode:self.lineBreakMode
|
884
|
+
alignment:self.textAlignment
|
885
|
+
lineSpacing:_lineSpacing
|
886
|
+
characterSpacing:_characterSpacing
|
887
|
+
kerningTable:_kerningTable
|
888
|
+
allowOrphans:_allowOrphans];
|
889
|
+
}
|
890
|
+
}
|
891
|
+
|
892
|
+
- (void)drawRect:(CGRect)rect
|
893
|
+
{
|
894
|
+
//get drawing context
|
895
|
+
BOOL subcontext = _oversampling > _minSamples || (self.backgroundColor && ![self.backgroundColor isEqual:[UIColor clearColor]]);
|
896
|
+
if (subcontext)
|
897
|
+
{
|
898
|
+
UIGraphicsBeginImageContextWithOptions(rect.size, NO, _oversampling);
|
899
|
+
}
|
900
|
+
CGContextRef context = UIGraphicsGetCurrentContext();
|
901
|
+
|
902
|
+
//apply insets
|
903
|
+
CGRect contentRect = CGRectMake(0.0f, 0.0f, self.bounds.size.width, self.bounds.size.height);
|
904
|
+
contentRect.origin.x += _textInsets.left;
|
905
|
+
contentRect.origin.y += _textInsets.top;
|
906
|
+
contentRect.size.width -= (_textInsets.left + _textInsets.right);
|
907
|
+
contentRect.size.height -= (_textInsets.top + _textInsets.bottom);
|
908
|
+
|
909
|
+
//get dimensions
|
910
|
+
CGFloat fontSize = 0.0f;
|
911
|
+
CGRect textRect = contentRect;
|
912
|
+
textRect.size = [self FXLabel_sizeThatFits:contentRect.size actualFontSize:&fontSize];
|
913
|
+
|
914
|
+
//set font
|
915
|
+
UIFont *font = [self.font fontWithSize:fontSize];
|
916
|
+
|
917
|
+
//adjust for minimum height
|
918
|
+
textRect.size.height = MAX(textRect.size.height, font.lineHeight);
|
919
|
+
|
920
|
+
//set color
|
921
|
+
UIColor *highlightedColor = self.highlightedTextColor ?: self.textColor;
|
922
|
+
UIColor *textColor = self.highlighted? highlightedColor: self.textColor;
|
923
|
+
textColor = textColor ?: [UIColor clearColor];
|
924
|
+
|
925
|
+
//set alignment
|
926
|
+
switch (self.textAlignment)
|
927
|
+
{
|
928
|
+
case NSTextAlignmentCenter:
|
929
|
+
{
|
930
|
+
textRect.origin.x = contentRect.origin.x + roundf((contentRect.size.width - textRect.size.width) / 2.0f);
|
931
|
+
break;
|
932
|
+
}
|
933
|
+
case NSTextAlignmentRight:
|
934
|
+
{
|
935
|
+
textRect.origin.x = contentRect.origin.x + contentRect.size.width - textRect.size.width;
|
936
|
+
break;
|
937
|
+
}
|
938
|
+
default:
|
939
|
+
{
|
940
|
+
textRect.origin.x = contentRect.origin.x;
|
941
|
+
break;
|
942
|
+
}
|
943
|
+
}
|
944
|
+
switch (self.contentMode)
|
945
|
+
{
|
946
|
+
case UIViewContentModeTop:
|
947
|
+
case UIViewContentModeTopLeft:
|
948
|
+
case UIViewContentModeTopRight:
|
949
|
+
{
|
950
|
+
textRect.origin.y = contentRect.origin.y;
|
951
|
+
break;
|
952
|
+
}
|
953
|
+
case UIViewContentModeBottom:
|
954
|
+
case UIViewContentModeBottomLeft:
|
955
|
+
case UIViewContentModeBottomRight:
|
956
|
+
{
|
957
|
+
textRect.origin.y = contentRect.origin.y + contentRect.size.height - textRect.size.height;
|
958
|
+
break;
|
959
|
+
}
|
960
|
+
default:
|
961
|
+
{
|
962
|
+
textRect.origin.y = contentRect.origin.y + (contentRect.size.height - textRect.size.height)/2.0f;
|
963
|
+
break;
|
964
|
+
}
|
965
|
+
}
|
966
|
+
|
967
|
+
BOOL hasShadow = self.shadowColor &&
|
968
|
+
![self.shadowColor isEqual:[UIColor clearColor]] &&
|
969
|
+
(shadowBlur > 0.0f || !CGSizeEqualToSize(self.shadowOffset, CGSizeZero));
|
970
|
+
|
971
|
+
BOOL hasInnerShadow = _innerShadowColor &&
|
972
|
+
![_innerShadowColor isEqual:[UIColor clearColor]] &&
|
973
|
+
(_innerShadowBlur > 0.0f || !CGSizeEqualToSize(_innerShadowOffset, CGSizeZero));
|
974
|
+
|
975
|
+
BOOL hasGradient = [_gradientColors count] > 1;
|
976
|
+
BOOL needsMask = hasInnerShadow || hasGradient;
|
977
|
+
|
978
|
+
CGImageRef alphaMask = NULL;
|
979
|
+
if (needsMask)
|
980
|
+
{
|
981
|
+
//draw mask
|
982
|
+
CGContextSaveGState(context);
|
983
|
+
[self FXLabel_drawTextInRect:textRect withFont:font];
|
984
|
+
CGContextRestoreGState(context);
|
985
|
+
|
986
|
+
//create an image mask from what we've drawn so far
|
987
|
+
alphaMask = CGBitmapContextCreateImage(context);
|
988
|
+
|
989
|
+
//clear the context
|
990
|
+
CGContextClearRect(context, textRect);
|
991
|
+
}
|
992
|
+
|
993
|
+
if (hasShadow)
|
994
|
+
{
|
995
|
+
//set up shadow
|
996
|
+
CGContextSaveGState(context);
|
997
|
+
CGFloat textAlpha = CGColorGetAlpha(textColor.CGColor);
|
998
|
+
CGContextSetShadowWithColor(context, self.shadowOffset, shadowBlur, self.shadowColor.CGColor);
|
999
|
+
[needsMask? [self.shadowColor colorWithAlphaComponent:textAlpha]: textColor setFill];
|
1000
|
+
[self FXLabel_drawTextInRect:textRect withFont:font];
|
1001
|
+
CGContextRestoreGState(context);
|
1002
|
+
}
|
1003
|
+
else if (!needsMask)
|
1004
|
+
{
|
1005
|
+
//just draw the text
|
1006
|
+
[textColor setFill];
|
1007
|
+
[self FXLabel_drawTextInRect:textRect withFont:font];
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
if (needsMask)
|
1011
|
+
{
|
1012
|
+
//clip the context
|
1013
|
+
CGContextSaveGState(context);
|
1014
|
+
CGContextTranslateCTM(context, 0, contentRect.size.height);
|
1015
|
+
CGContextScaleCTM(context, 1.0, -1.0);
|
1016
|
+
CGContextClipToMask(context, contentRect, alphaMask);
|
1017
|
+
|
1018
|
+
if (hasGradient)
|
1019
|
+
{
|
1020
|
+
//create array of pre-blended CGColors
|
1021
|
+
NSMutableArray *colors = [NSMutableArray arrayWithCapacity:[_gradientColors count]];
|
1022
|
+
for (UIColor *color in _gradientColors)
|
1023
|
+
{
|
1024
|
+
UIColor *blended = [self FXLabel_color:color.CGColor blendedWithColor:textColor.CGColor];
|
1025
|
+
[colors addObject:(__bridge id)blended.CGColor];
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
//draw gradient
|
1029
|
+
CGContextSaveGState(context);
|
1030
|
+
CGContextScaleCTM(context, 1.0, -1.0);
|
1031
|
+
CGContextTranslateCTM(context, 0, -contentRect.size.height);
|
1032
|
+
CGGradientRef gradient = CGGradientCreateWithColors(NULL, (__bridge CFArrayRef)colors, NULL);
|
1033
|
+
CGPoint startPoint = CGPointMake(textRect.origin.x + _gradientStartPoint.x * textRect.size.width,
|
1034
|
+
textRect.origin.y + _gradientStartPoint.y * textRect.size.height);
|
1035
|
+
CGPoint endPoint = CGPointMake(textRect.origin.x + _gradientEndPoint.x * textRect.size.width,
|
1036
|
+
textRect.origin.y + _gradientEndPoint.y * textRect.size.height);
|
1037
|
+
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint,
|
1038
|
+
kCGGradientDrawsAfterEndLocation | kCGGradientDrawsBeforeStartLocation);
|
1039
|
+
CGGradientRelease(gradient);
|
1040
|
+
CGContextRestoreGState(context);
|
1041
|
+
}
|
1042
|
+
else
|
1043
|
+
{
|
1044
|
+
//fill text
|
1045
|
+
[textColor setFill];
|
1046
|
+
UIRectFill(textRect);
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
if (hasInnerShadow)
|
1050
|
+
{
|
1051
|
+
//generate inverse mask
|
1052
|
+
UIGraphicsBeginImageContextWithOptions(rect.size, NO, _oversampling);
|
1053
|
+
CGContextRef shadowContext = UIGraphicsGetCurrentContext();
|
1054
|
+
[[_innerShadowColor colorWithAlphaComponent:1.0f] setFill];
|
1055
|
+
UIRectFill(rect);
|
1056
|
+
CGContextClipToMask(shadowContext, rect, alphaMask);
|
1057
|
+
CGContextClearRect(shadowContext, rect);
|
1058
|
+
UIImage *shadowImage = UIGraphicsGetImageFromCurrentImageContext();
|
1059
|
+
UIGraphicsEndImageContext();
|
1060
|
+
|
1061
|
+
//draw shadow
|
1062
|
+
CGContextSetShadowWithColor(context, _innerShadowOffset, _innerShadowBlur, _innerShadowColor.CGColor);
|
1063
|
+
CGContextSetBlendMode(context, kCGBlendModeDarken);
|
1064
|
+
[shadowImage drawInRect:rect];
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
//end clipping
|
1068
|
+
CGContextRestoreGState(context);
|
1069
|
+
CGImageRelease(alphaMask);
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
if (subcontext)
|
1073
|
+
{
|
1074
|
+
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
1075
|
+
UIGraphicsEndImageContext();
|
1076
|
+
[image drawInRect:rect];
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
|
1080
|
+
@end
|