1/*
2 * Copyright (C) 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#if PLATFORM(IOS)
27
28#import "WebSelectionRect.h"
29
30@implementation WebSelectionRect
31
32@synthesize rect = m_rect;
33@synthesize writingDirection = m_writingDirection;
34@synthesize isLineBreak = m_isLineBreak;
35@synthesize isFirstOnLine = m_isFirstOnLine;
36@synthesize isLastOnLine = m_isLastOnLine;
37@synthesize containsStart = m_containsStart;
38@synthesize containsEnd = m_containsEnd;
39@synthesize isInFixedPosition = m_isInFixedPosition;
40@synthesize isHorizontal = m_isHorizontal;
41
42+ (WebSelectionRect *)selectionRect
43{
44    return [[[self alloc] init] autorelease];
45}
46
47+ (CGRect)startEdge:(NSArray *)rects
48{
49    if (rects.count == 0)
50        return CGRectZero;
51
52    WebSelectionRect *selectionRect = nil;
53    for (WebSelectionRect *srect in rects) {
54        if (srect.containsStart) {
55            selectionRect = srect;
56            break;
57        }
58    }
59    if (!selectionRect)
60        selectionRect = [rects objectAtIndex:0];
61
62    CGRect rect = selectionRect.rect;
63
64    if (!selectionRect.isHorizontal) {
65        switch (selectionRect.writingDirection) {
66            case WKWritingDirectionNatural:
67            case WKWritingDirectionLeftToRight:
68                // collapse to top edge
69                rect.size.height = 1;
70                break;
71            case WKWritingDirectionRightToLeft:
72                // collapse to bottom edge
73                rect.origin.y += (rect.size.height - 1);
74                rect.size.height = 1;
75                break;
76        }
77        return rect;
78    }
79
80    switch (selectionRect.writingDirection) {
81        case WKWritingDirectionNatural:
82        case WKWritingDirectionLeftToRight:
83            // collapse to left edge
84            rect.size.width = 1;
85            break;
86        case WKWritingDirectionRightToLeft:
87            // collapse to right edge
88            rect.origin.x += (rect.size.width - 1);
89            rect.size.width = 1;
90            break;
91    }
92    return rect;
93}
94
95+ (CGRect)endEdge:(NSArray *)rects
96{
97    if (rects.count == 0)
98        return CGRectZero;
99
100    WebSelectionRect *selectionRect = nil;
101    for (WebSelectionRect *srect in rects) {
102        if (srect.containsEnd) {
103            selectionRect = srect;
104            break;
105        }
106    }
107    if (!selectionRect)
108        selectionRect = [rects lastObject];
109
110    CGRect rect = selectionRect.rect;
111
112    if (!selectionRect.isHorizontal) {
113        switch (selectionRect.writingDirection) {
114            case WKWritingDirectionNatural:
115            case WKWritingDirectionLeftToRight:
116                // collapse to bottom edge
117                rect.origin.y += (rect.size.height - 1);
118                rect.size.height = 1;
119                break;
120            case WKWritingDirectionRightToLeft:
121                // collapse to top edge
122                rect.size.height = 1;
123                break;
124        }
125        return rect;
126    }
127
128    switch (selectionRect.writingDirection) {
129        case WKWritingDirectionNatural:
130        case WKWritingDirectionLeftToRight:
131            // collapse to right edge
132            rect.origin.x += (rect.size.width - 1);
133            rect.size.width = 1;
134            break;
135        case WKWritingDirectionRightToLeft:
136            // collapse to left edge
137            rect.size.width = 1;
138            break;
139    }
140    return rect;
141}
142
143- (id)init
144{
145    self = [super init];
146    if (!self)
147        return nil;
148
149    self.rect = CGRectZero;
150    self.writingDirection = WKWritingDirectionLeftToRight;
151    self.isLineBreak = NO;
152    self.isFirstOnLine = NO;
153    self.isLastOnLine = NO;
154    self.containsStart = NO;
155    self.containsEnd = NO;
156    self.isInFixedPosition = NO;
157    self.isHorizontal = NO;
158
159    return self;
160}
161
162- (id)copyWithZone:(NSZone *)zone
163{
164    WebSelectionRect *copy = [[WebSelectionRect selectionRect] retain];
165    copy.rect = self.rect;
166    copy.writingDirection = self.writingDirection;
167    copy.isLineBreak = self.isLineBreak;
168    copy.isFirstOnLine = self.isFirstOnLine;
169    copy.isLastOnLine = self.isLastOnLine;
170    copy.containsStart = self.containsStart;
171    copy.containsEnd = self.containsEnd;
172    copy.isInFixedPosition = self.isInFixedPosition;
173    copy.isHorizontal = self.isHorizontal;
174    return copy;
175}
176
177- (NSString *)description
178{
179    return [NSString stringWithFormat:@"<WebSelectionRect: %p> : { %.1f,%.1f,%.1f,%.1f } %@%@%@%@%@%@%@%@",
180        self,
181        self.rect.origin.x, self.rect.origin.y, self.rect.size.width, self.rect.size.height,
182        self.writingDirection == WKWritingDirectionLeftToRight ? @"[LTR]" : @"[RTL]",
183        self.isLineBreak ? @" [BR]" : @"",
184        self.isFirstOnLine ? @" [FIRST]" : @"",
185        self.isLastOnLine ? @" [LAST]" : @"",
186        self.containsStart ? @" [START]" : @"",
187        self.containsEnd ? @" [END]" : @"",
188        self.isInFixedPosition ? @" [FIXED]" : @"",
189        !self.isHorizontal ? @" [VERTICAL]" : @""];
190}
191
192@end
193
194#endif  // PLATFORM(IOS)
195