/* * Copyright (c) 2012, Google Inc. All rights reserved. * Copyright (C) 2015, 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: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT * OWNER OR 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. */ #ifndef WritingMode_h #define WritingMode_h namespace WebCore { enum TextDirection { LTR, RTL }; inline bool isLeftToRightDirection(TextDirection direction) { return direction == LTR; } enum WritingMode { TopToBottomWritingMode = 0, // horizontal-tb BottomToTopWritingMode = 1, // horizontal-bt LeftToRightWritingMode = 2, // vertical-lr RightToLeftWritingMode = 3, // vertical-rl }; #define MAKE_TEXT_FLOW(writingMode, direction) ((writingMode) << 1 | (direction)) // Define the text flow in terms of the writing mode and the text direction. The first // part is the line growing direction and the second part is the block growing direction. enum TextFlow { InlineEastBlockSouth = MAKE_TEXT_FLOW(TopToBottomWritingMode, LTR), InlineWestBlockSouth = MAKE_TEXT_FLOW(TopToBottomWritingMode, RTL), InlineEastBlockNorth = MAKE_TEXT_FLOW(BottomToTopWritingMode, LTR), InlineWestBlockNorth = MAKE_TEXT_FLOW(BottomToTopWritingMode, RTL), InlineSouthBlockEast = MAKE_TEXT_FLOW(LeftToRightWritingMode, LTR), InlineSouthBlockWest = MAKE_TEXT_FLOW(LeftToRightWritingMode, RTL), InlineNorthBlockEast = MAKE_TEXT_FLOW(RightToLeftWritingMode, LTR), InlineNorthBlockWest = MAKE_TEXT_FLOW(RightToLeftWritingMode, RTL) }; inline TextFlow makeTextFlow(WritingMode writingMode, TextDirection direction) { return static_cast(MAKE_TEXT_FLOW(writingMode, direction)); } #undef MAKE_TEXT_FLOW const unsigned TextFlowReversedMask = 1; const unsigned TextFlowFlippedMask = 2; const unsigned TextFlowVerticalMask = 4; inline bool isReversedTextFlow(TextFlow textflow) { return textflow & TextFlowReversedMask; } inline bool isFlippedTextFlow(TextFlow textflow) { return textflow & TextFlowFlippedMask; } inline bool isVerticalTextFlow(TextFlow textflow) { return textflow & TextFlowVerticalMask; } // Lines have vertical orientation; modes vertical-lr or vertical-rl. inline bool isVerticalWritingMode(WritingMode writingMode) { return isVerticalTextFlow(makeTextFlow(writingMode, LTR)); } // Block progression increases in the opposite direction to normal; modes vertical-rl or horizontal-bt. inline bool isFlippedWritingMode(WritingMode writingMode) { return isFlippedTextFlow(makeTextFlow(writingMode, LTR)); } // Lines have horizontal orientation; modes horizontal-tb or horizontal-bt. inline bool isHorizontalWritingMode(WritingMode writingMode) { return !isVerticalWritingMode(writingMode); } // Bottom of the line occurs earlier in the block; modes vertical-lr or horizontal-bt. inline bool isFlippedLinesWritingMode(WritingMode writingMode) { return isVerticalWritingMode(writingMode) != isFlippedWritingMode(writingMode); } enum LogicalBoxSide { BeforeSide, EndSide, AfterSide, StartSide }; enum PhysicalBoxSide { NilSide = -1, TopSide, RightSide, BottomSide, LeftSide }; inline bool isHorizontalPhysicalSide(PhysicalBoxSide physicalSide) { return physicalSide == LeftSide || physicalSide == RightSide; } inline PhysicalBoxSide mirrorPhysicalSide(PhysicalBoxSide physicalSide) { // top <-> bottom and left <-> right conversion return static_cast((static_cast(physicalSide) + 2) % 4); } inline PhysicalBoxSide rotatePhysicalSide(PhysicalBoxSide physicalSide) { // top <-> left and right <-> bottom conversion bool horizontalSide = isHorizontalPhysicalSide(physicalSide); return static_cast((static_cast(physicalSide) + (horizontalSide ? 1 : 3)) % 4); } inline PhysicalBoxSide mapLogicalSideToPhysicalSide(TextFlow textflow, LogicalBoxSide logicalSide) { PhysicalBoxSide physicalSide = static_cast(logicalSide); bool horizontalSide = isHorizontalPhysicalSide(physicalSide); if (isVerticalTextFlow(textflow)) physicalSide = rotatePhysicalSide(physicalSide); if ((horizontalSide && isReversedTextFlow(textflow)) || (!horizontalSide && isFlippedTextFlow(textflow))) physicalSide = mirrorPhysicalSide(physicalSide); return physicalSide; } inline PhysicalBoxSide mapLogicalSideToPhysicalSide(WritingMode writingMode, LogicalBoxSide logicalSide) { // Set the direction such that side is mirrored if isFlippedWritingMode() is true TextDirection direction = isFlippedWritingMode(writingMode) ? RTL : LTR; return mapLogicalSideToPhysicalSide(makeTextFlow(writingMode, direction), logicalSide); } } // namespace WebCore #endif // WritingMode_h