220 lines
8.0 KiB
C++
220 lines
8.0 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "TextDirection.h"
|
|
#include <array>
|
|
|
|
namespace WebCore {
|
|
|
|
enum class WritingMode : uint8_t {
|
|
TopToBottom = 0, // horizontal-tb
|
|
BottomToTop = 1, // horizontal-bt
|
|
LeftToRight = 2, // vertical-lr
|
|
RightToLeft = 3, // vertical-rl
|
|
};
|
|
|
|
constexpr unsigned makeTextFlowInitalizer(WritingMode writingMode, TextDirection direction)
|
|
{
|
|
return static_cast<unsigned>(writingMode) << 1 | static_cast<unsigned>(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 = makeTextFlowInitalizer(WritingMode::TopToBottom, TextDirection::LTR),
|
|
InlineWestBlockSouth = makeTextFlowInitalizer(WritingMode::TopToBottom, TextDirection::RTL),
|
|
InlineEastBlockNorth = makeTextFlowInitalizer(WritingMode::BottomToTop, TextDirection::LTR),
|
|
InlineWestBlockNorth = makeTextFlowInitalizer(WritingMode::BottomToTop, TextDirection::RTL),
|
|
InlineSouthBlockEast = makeTextFlowInitalizer(WritingMode::LeftToRight, TextDirection::LTR),
|
|
InlineSouthBlockWest = makeTextFlowInitalizer(WritingMode::LeftToRight, TextDirection::RTL),
|
|
InlineNorthBlockEast = makeTextFlowInitalizer(WritingMode::RightToLeft, TextDirection::LTR),
|
|
InlineNorthBlockWest = makeTextFlowInitalizer(WritingMode::RightToLeft, TextDirection::RTL)
|
|
};
|
|
|
|
constexpr inline TextFlow makeTextFlow(WritingMode writingMode, TextDirection direction)
|
|
{
|
|
return static_cast<TextFlow>(makeTextFlowInitalizer(writingMode, direction));
|
|
}
|
|
|
|
constexpr unsigned TextFlowReversedMask = 1;
|
|
constexpr unsigned TextFlowFlippedMask = 2;
|
|
constexpr unsigned TextFlowVerticalMask = 4;
|
|
|
|
constexpr inline bool isReversedTextFlow(TextFlow textflow)
|
|
{
|
|
return textflow & TextFlowReversedMask;
|
|
}
|
|
|
|
constexpr inline bool isFlippedTextFlow(TextFlow textflow)
|
|
{
|
|
return textflow & TextFlowFlippedMask;
|
|
}
|
|
|
|
constexpr inline bool isVerticalTextFlow(TextFlow textflow)
|
|
{
|
|
return textflow & TextFlowVerticalMask;
|
|
}
|
|
|
|
constexpr inline bool isFlippedLinesTextFlow(TextFlow textflow)
|
|
{
|
|
return isFlippedTextFlow(textflow) != isVerticalTextFlow(textflow);
|
|
}
|
|
|
|
// Lines have vertical orientation; modes vertical-lr or vertical-rl.
|
|
constexpr inline bool isVerticalWritingMode(WritingMode writingMode)
|
|
{
|
|
return isVerticalTextFlow(makeTextFlow(writingMode, TextDirection::LTR));
|
|
}
|
|
|
|
// Block progression increases in the opposite direction to normal; modes vertical-rl or horizontal-bt.
|
|
constexpr inline bool isFlippedWritingMode(WritingMode writingMode)
|
|
{
|
|
return isFlippedTextFlow(makeTextFlow(writingMode, TextDirection::LTR));
|
|
}
|
|
|
|
// Lines have horizontal orientation; modes horizontal-tb or horizontal-bt.
|
|
constexpr inline bool isHorizontalWritingMode(WritingMode writingMode)
|
|
{
|
|
return !isVerticalWritingMode(writingMode);
|
|
}
|
|
|
|
// Bottom of the line occurs earlier in the block; modes vertical-lr or horizontal-bt.
|
|
constexpr inline bool isFlippedLinesWritingMode(WritingMode writingMode)
|
|
{
|
|
return isFlippedLinesTextFlow(makeTextFlow(writingMode, TextDirection::LTR));
|
|
}
|
|
|
|
enum class LogicalBoxSide : uint8_t {
|
|
BlockStart,
|
|
InlineEnd,
|
|
BlockEnd,
|
|
InlineStart
|
|
};
|
|
|
|
enum class BoxSide : uint8_t {
|
|
Top,
|
|
Right,
|
|
Bottom,
|
|
Left
|
|
};
|
|
|
|
enum class LogicalBoxCorner : uint8_t {
|
|
StartStart,
|
|
StartEnd,
|
|
EndStart,
|
|
EndEnd
|
|
};
|
|
|
|
// The mapping is with the first start/end giving the block axis side,
|
|
// and the second the inline-axis side, i.e. patterned as 'border-block-inline-radius'.
|
|
enum class BoxCorner : uint8_t {
|
|
TopLeft,
|
|
TopRight,
|
|
BottomRight,
|
|
BottomLeft
|
|
};
|
|
|
|
enum class LogicalBoxAxis : uint8_t {
|
|
Inline,
|
|
Block
|
|
};
|
|
|
|
enum class BoxAxis : uint8_t {
|
|
Horizontal,
|
|
Vertical
|
|
};
|
|
|
|
constexpr std::array<BoxSide, 4> allBoxSides = { BoxSide::Top, BoxSide::Right, BoxSide::Bottom, BoxSide::Left };
|
|
|
|
constexpr inline bool isHorizontalPhysicalSide(BoxSide physicalSide)
|
|
{
|
|
return physicalSide == BoxSide::Left || physicalSide == BoxSide::Right;
|
|
}
|
|
|
|
constexpr inline BoxSide mirrorPhysicalSide(BoxSide physicalSide)
|
|
{
|
|
// top <-> bottom and left <-> right conversion
|
|
return static_cast<BoxSide>((static_cast<int>(physicalSide) + 2) % 4);
|
|
}
|
|
|
|
constexpr inline BoxSide rotatePhysicalSide(BoxSide physicalSide)
|
|
{
|
|
// top <-> left and right <-> bottom conversion
|
|
bool horizontalSide = isHorizontalPhysicalSide(physicalSide);
|
|
return static_cast<BoxSide>((static_cast<int>(physicalSide) + (horizontalSide ? 1 : 3)) % 4);
|
|
}
|
|
|
|
constexpr inline BoxSide mapLogicalSideToPhysicalSide(TextFlow textflow, LogicalBoxSide logicalSide)
|
|
{
|
|
BoxSide physicalSide = static_cast<BoxSide>(logicalSide);
|
|
bool horizontalSide = isHorizontalPhysicalSide(physicalSide);
|
|
|
|
if (isVerticalTextFlow(textflow))
|
|
physicalSide = rotatePhysicalSide(physicalSide);
|
|
|
|
if ((horizontalSide && isReversedTextFlow(textflow)) || (!horizontalSide && isFlippedTextFlow(textflow)))
|
|
physicalSide = mirrorPhysicalSide(physicalSide);
|
|
|
|
return physicalSide;
|
|
}
|
|
|
|
constexpr inline BoxSide mapLogicalSideToPhysicalSide(WritingMode writingMode, LogicalBoxSide logicalSide)
|
|
{
|
|
// Set the direction such that side is mirrored if isFlippedWritingMode() is true
|
|
TextDirection direction = isFlippedWritingMode(writingMode) ? TextDirection::RTL : TextDirection::LTR;
|
|
return mapLogicalSideToPhysicalSide(makeTextFlow(writingMode, direction), logicalSide);
|
|
}
|
|
|
|
constexpr inline BoxCorner mapLogicalCornerToPhysicalCorner(TextFlow textflow, LogicalBoxCorner logicalBoxCorner)
|
|
{
|
|
bool isBlockStart = logicalBoxCorner == LogicalBoxCorner::StartStart || logicalBoxCorner == LogicalBoxCorner::StartEnd;
|
|
bool isInlineStart = logicalBoxCorner == LogicalBoxCorner::StartStart || logicalBoxCorner == LogicalBoxCorner::EndStart;
|
|
if (isBlockStart == isFlippedTextFlow(textflow)) {
|
|
if (isInlineStart == isReversedTextFlow(textflow))
|
|
return BoxCorner::BottomRight;
|
|
} else if (isInlineStart != isReversedTextFlow(textflow))
|
|
return BoxCorner::TopLeft;
|
|
if (isBlockStart == isFlippedLinesTextFlow(textflow))
|
|
return BoxCorner::BottomLeft;
|
|
return BoxCorner::TopRight;
|
|
}
|
|
|
|
constexpr inline BoxAxis mapLogicalAxisToPhysicalAxis(TextFlow textflow, LogicalBoxAxis logicalAxis)
|
|
{
|
|
if (isVerticalTextFlow(textflow))
|
|
return logicalAxis == LogicalBoxAxis::Inline ? BoxAxis::Vertical : BoxAxis::Horizontal;
|
|
return logicalAxis == LogicalBoxAxis::Inline ? BoxAxis::Horizontal : BoxAxis::Vertical;
|
|
}
|
|
|
|
} // namespace WebCore
|