WebSelectionRect.m   [plain text]


/*
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#if PLATFORM(IOS)

#import "WebSelectionRect.h"

@implementation WebSelectionRect {
    CGRect m_rect;
    WKWritingDirection m_writingDirection;
    BOOL m_isLineBreak;
    BOOL m_isFirstOnLine;
    BOOL m_isLastOnLine;
    BOOL m_containsStart;
    BOOL m_containsEnd;
    BOOL m_isInFixedPosition;
    BOOL m_isHorizontal;
}

@synthesize rect = m_rect;
@synthesize writingDirection = m_writingDirection;
@synthesize isLineBreak = m_isLineBreak;
@synthesize isFirstOnLine = m_isFirstOnLine;
@synthesize isLastOnLine = m_isLastOnLine;
@synthesize containsStart = m_containsStart;
@synthesize containsEnd = m_containsEnd;
@synthesize isInFixedPosition = m_isInFixedPosition;
@synthesize isHorizontal = m_isHorizontal;

+ (WebSelectionRect *)selectionRect
{
    return [[(WebSelectionRect *)[self alloc] init] autorelease];
}

+ (CGRect)startEdge:(NSArray *)rects
{
    if (rects.count == 0)
        return CGRectZero;

    WebSelectionRect *selectionRect = nil;
    for (WebSelectionRect *srect in rects) {
        if (srect.containsStart) {
            selectionRect = srect;
            break;
        }
    }
    if (!selectionRect)
        selectionRect = [rects objectAtIndex:0];
    
    CGRect rect = selectionRect.rect;
    
    if (!selectionRect.isHorizontal) {
        switch (selectionRect.writingDirection) {
            case WKWritingDirectionNatural:
            case WKWritingDirectionLeftToRight:
                // collapse to top edge
                rect.size.height = 1;
                break;
            case WKWritingDirectionRightToLeft:
                // collapse to bottom edge
                rect.origin.y += (rect.size.height - 1);
                rect.size.height = 1;
                break;
        }
        return rect;
    }
    
    switch (selectionRect.writingDirection) {
        case WKWritingDirectionNatural:
        case WKWritingDirectionLeftToRight:
            // collapse to left edge
            rect.size.width = 1;
            break;
        case WKWritingDirectionRightToLeft:
            // collapse to right edge
            rect.origin.x += (rect.size.width - 1);
            rect.size.width = 1;
            break;
    }
    return rect;
}

+ (CGRect)endEdge:(NSArray *)rects
{
    if (rects.count == 0)
        return CGRectZero;

    WebSelectionRect *selectionRect = nil;
    for (WebSelectionRect *srect in rects) {
        if (srect.containsEnd) {
            selectionRect = srect;
            break;
        }
    }
    if (!selectionRect)
        selectionRect = [rects lastObject];

    CGRect rect = selectionRect.rect;
    
    if (!selectionRect.isHorizontal) {
        switch (selectionRect.writingDirection) {
            case WKWritingDirectionNatural:
            case WKWritingDirectionLeftToRight:
                // collapse to bottom edge
                rect.origin.y += (rect.size.height - 1);
                rect.size.height = 1;
                break;
            case WKWritingDirectionRightToLeft:
                // collapse to top edge
                rect.size.height = 1;
                break;
        }
        return rect;
    }
    
    switch (selectionRect.writingDirection) {
        case WKWritingDirectionNatural:
        case WKWritingDirectionLeftToRight:
            // collapse to right edge
            rect.origin.x += (rect.size.width - 1);
            rect.size.width = 1;
            break;
        case WKWritingDirectionRightToLeft:
            // collapse to left edge
            rect.size.width = 1;
            break;
    }
    return rect;
}

- (id)init
{
    self = [super init];
    if (!self)
        return nil;
    
    self.rect = CGRectZero;
    self.writingDirection = WKWritingDirectionLeftToRight;
    self.isLineBreak = NO;
    self.isFirstOnLine = NO;
    self.isLastOnLine = NO;
    self.containsStart = NO;
    self.containsEnd = NO;
    self.isInFixedPosition = NO;
    self.isHorizontal = NO;
    
    return self;
}

- (id)copyWithZone:(NSZone *)zone
{
    WebSelectionRect *copy = [[WebSelectionRect selectionRect] retain];
    copy.rect = self.rect;
    copy.writingDirection = self.writingDirection;
    copy.isLineBreak = self.isLineBreak;
    copy.isFirstOnLine = self.isFirstOnLine;
    copy.isLastOnLine = self.isLastOnLine;
    copy.containsStart = self.containsStart;
    copy.containsEnd = self.containsEnd;
    copy.isInFixedPosition = self.isInFixedPosition;
    copy.isHorizontal = self.isHorizontal;
    return copy;
}

- (NSString *)description
{
    return [NSString stringWithFormat:@"<WebSelectionRect: %p> : { %.1f,%.1f,%.1f,%.1f } %@%@%@%@%@%@%@%@",
        self, 
        self.rect.origin.x, self.rect.origin.y, self.rect.size.width, self.rect.size.height,
        self.writingDirection == WKWritingDirectionLeftToRight ? @"[LTR]" : @"[RTL]",
        self.isLineBreak ? @" [BR]" : @"",
        self.isFirstOnLine ? @" [FIRST]" : @"",
        self.isLastOnLine ? @" [LAST]" : @"",
        self.containsStart ? @" [START]" : @"",
        self.containsEnd ? @" [END]" : @"",
        self.isInFixedPosition ? @" [FIXED]" : @"",
        !self.isHorizontal ? @" [VERTICAL]" : @""];
}

@end

#endif  // PLATFORM(IOS)