This source file includes following definitions.
- startKeyword
- middleKeyword
- endKeyword
- leftKeyword
- rightKeyword
- horizontalKeyword
- verticalGrowingLeftKeyword
- verticalGrowingRightKeyword
- isInvalidPercentage
- m_cue
- applyCSSProperties
- createRenderer
- m_notifyRegion
- toString
- displayTreeInternal
- cueDidChange
- vertical
- setVertical
- setSnapToLines
- setLine
- setPosition
- setSize
- align
- setAlign
- setText
- createVTTNodeTree
- copyVTTNodeToDOMTree
- getCueAsHTML
- createCueRenderingTree
- setRegionId
- notifyRegionWhenRemovingDisplayTree
- calculateComputedLinePosition
- atParagraphSeparator
- determineDirectionality
- determineTextDirection
- calculateDisplayParameters
- markFutureAndPastNodes
- updateDisplayTree
- getDisplayTree
- removeDisplayTree
- updateDisplay
- getPositionCoordinates
- settingName
- scanPercentage
- parseSettings
- getCSSAlignment
- getCSSWritingDirection
- getCSSWritingMode
- getCSSSize
- getCSSPosition
- executionContext
- document
#include "config.h"
#include "core/html/track/vtt/VTTCue.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionMessages.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/DocumentFragment.h"
#include "core/dom/NodeTraversal.h"
#include "core/events/Event.h"
#include "core/html/HTMLDivElement.h"
#include "core/html/track/TextTrack.h"
#include "core/html/track/TextTrackCueList.h"
#include "core/html/track/vtt/VTTElement.h"
#include "core/html/track/vtt/VTTParser.h"
#include "core/html/track/vtt/VTTRegionList.h"
#include "core/html/track/vtt/VTTScanner.h"
#include "core/rendering/RenderVTTCue.h"
#include "platform/text/BidiResolver.h"
#include "platform/text/TextRunIterator.h"
#include "wtf/MathExtras.h"
#include "wtf/text/StringBuilder.h"
namespace WebCore {
static const int undefinedPosition = -1;
static const int undefinedSize = -1;
static const CSSValueID displayWritingModeMap[] = {
CSSValueHorizontalTb, CSSValueVerticalRl, CSSValueVerticalLr
};
COMPILE_ASSERT(WTF_ARRAY_LENGTH(displayWritingModeMap) == VTTCue::NumberOfWritingDirections,
displayWritingModeMap_has_wrong_size);
static const CSSValueID displayAlignmentMap[] = {
CSSValueStart, CSSValueCenter, CSSValueEnd, CSSValueLeft, CSSValueRight
};
COMPILE_ASSERT(WTF_ARRAY_LENGTH(displayAlignmentMap) == VTTCue::NumberOfAlignments,
displayAlignmentMap_has_wrong_size);
static const String& startKeyword()
{
DEFINE_STATIC_LOCAL(const String, start, ("start"));
return start;
}
static const String& middleKeyword()
{
DEFINE_STATIC_LOCAL(const String, middle, ("middle"));
return middle;
}
static const String& endKeyword()
{
DEFINE_STATIC_LOCAL(const String, end, ("end"));
return end;
}
static const String& leftKeyword()
{
DEFINE_STATIC_LOCAL(const String, left, ("left"));
return left;
}
static const String& rightKeyword()
{
DEFINE_STATIC_LOCAL(const String, right, ("right"));
return right;
}
static const String& horizontalKeyword()
{
return emptyString();
}
static const String& verticalGrowingLeftKeyword()
{
DEFINE_STATIC_LOCAL(const String, verticalrl, ("rl"));
return verticalrl;
}
static const String& verticalGrowingRightKeyword()
{
DEFINE_STATIC_LOCAL(const String, verticallr, ("lr"));
return verticallr;
}
static bool isInvalidPercentage(double value, ExceptionState& exceptionState)
{
if (TextTrackCue::isInfiniteOrNonNumber(value, exceptionState))
return true;
if (value < 0 || value > 100) {
exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange("value", value, 0.0, ExceptionMessages::InclusiveBound, 100.0, ExceptionMessages::InclusiveBound));
return true;
}
return false;
}
VTTCueBox::VTTCueBox(Document& document, VTTCue* cue)
: HTMLDivElement(document)
, m_cue(cue)
{
setShadowPseudoId(AtomicString("-webkit-media-text-track-display", AtomicString::ConstructFromLiteral));
}
void VTTCueBox::applyCSSProperties(const IntSize&)
{
if (!m_cue->regionId().isEmpty()) {
setInlineStyleProperty(CSSPropertyPosition, CSSValueRelative);
return;
}
setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext);
setInlineStyleProperty(CSSPropertyDirection, m_cue->getCSSWritingDirection());
setInlineStyleProperty(CSSPropertyWebkitWritingMode, m_cue->getCSSWritingMode());
std::pair<float, float> position = m_cue->getCSSPosition();
setInlineStyleProperty(CSSPropertyTop, position.second, CSSPrimitiveValue::CSS_PERCENTAGE);
setInlineStyleProperty(CSSPropertyLeft, position.first, CSSPrimitiveValue::CSS_PERCENTAGE);
if (m_cue->vertical() == horizontalKeyword()) {
setInlineStyleProperty(CSSPropertyWidth, static_cast<double>(m_cue->getCSSSize()), CSSPrimitiveValue::CSS_PERCENTAGE);
setInlineStyleProperty(CSSPropertyHeight, CSSValueAuto);
} else {
setInlineStyleProperty(CSSPropertyWidth, CSSValueAuto);
setInlineStyleProperty(CSSPropertyHeight, static_cast<double>(m_cue->getCSSSize()), CSSPrimitiveValue::CSS_PERCENTAGE);
}
setInlineStyleProperty(CSSPropertyTextAlign, m_cue->getCSSAlignment());
if (!m_cue->snapToLines()) {
setInlineStyleProperty(CSSPropertyWebkitTransform,
String::format("translate(-%.2f%%, -%.2f%%)", position.first, position.second));
setInlineStyleProperty(CSSPropertyWhiteSpace, CSSValuePre);
}
}
RenderObject* VTTCueBox::createRenderer(RenderStyle*)
{
return new RenderVTTCue(this);
}
VTTCue::VTTCue(Document& document, double startTime, double endTime, const String& text)
: TextTrackCue(startTime, endTime)
, m_text(text)
, m_linePosition(undefinedPosition)
, m_computedLinePosition(undefinedPosition)
, m_textPosition(50)
, m_cueSize(100)
, m_writingDirection(Horizontal)
, m_cueAlignment(Middle)
, m_vttNodeTree(nullptr)
, m_cueBackgroundBox(HTMLDivElement::create(document))
, m_displayDirection(CSSValueLtr)
, m_displaySize(undefinedSize)
, m_snapToLines(true)
, m_displayTreeShouldChange(true)
, m_notifyRegion(true)
{
ScriptWrappable::init(this);
}
VTTCue::~VTTCue()
{
displayTreeInternal()->remove(ASSERT_NO_EXCEPTION);
}
#ifndef NDEBUG
String VTTCue::toString() const
{
return String::format("%p id=%s interval=%f-->%f cue=%s)", this, id().utf8().data(), startTime(), endTime(), text().utf8().data());
}
#endif
PassRefPtr<VTTCueBox> VTTCue::displayTreeInternal()
{
if (!m_displayTree)
m_displayTree = VTTCueBox::create(document(), this);
return m_displayTree;
}
void VTTCue::cueDidChange()
{
TextTrackCue::cueDidChange();
m_displayTreeShouldChange = true;
}
const String& VTTCue::vertical() const
{
switch (m_writingDirection) {
case Horizontal:
return horizontalKeyword();
case VerticalGrowingLeft:
return verticalGrowingLeftKeyword();
case VerticalGrowingRight:
return verticalGrowingRightKeyword();
default:
ASSERT_NOT_REACHED();
return emptyString();
}
}
void VTTCue::setVertical(const String& value, ExceptionState& exceptionState)
{
WritingDirection direction = m_writingDirection;
if (value == horizontalKeyword())
direction = Horizontal;
else if (value == verticalGrowingLeftKeyword())
direction = VerticalGrowingLeft;
else if (value == verticalGrowingRightKeyword())
direction = VerticalGrowingRight;
else
exceptionState.throwDOMException(SyntaxError, "The value provided ('" + value + "') is invalid. Only 'rl', 'lr', and the empty string are accepted.");
if (direction == m_writingDirection)
return;
cueWillChange();
m_writingDirection = direction;
cueDidChange();
}
void VTTCue::setSnapToLines(bool value)
{
if (m_snapToLines == value)
return;
cueWillChange();
m_snapToLines = value;
cueDidChange();
}
void VTTCue::setLine(int position, ExceptionState& exceptionState)
{
if (!m_snapToLines && (position < 0 || position > 100)) {
exceptionState.throwDOMException(IndexSizeError, "The snap-to-lines flag is not set, and the value provided (" + String::number(position) + ") is not between 0 and 100.");
return;
}
if (m_linePosition == position)
return;
cueWillChange();
m_linePosition = position;
m_computedLinePosition = calculateComputedLinePosition();
cueDidChange();
}
void VTTCue::setPosition(int position, ExceptionState& exceptionState)
{
if (isInvalidPercentage(position, exceptionState))
return;
if (m_textPosition == position)
return;
cueWillChange();
m_textPosition = position;
cueDidChange();
}
void VTTCue::setSize(int size, ExceptionState& exceptionState)
{
if (isInvalidPercentage(size, exceptionState))
return;
if (m_cueSize == size)
return;
cueWillChange();
m_cueSize = size;
cueDidChange();
}
const String& VTTCue::align() const
{
switch (m_cueAlignment) {
case Start:
return startKeyword();
case Middle:
return middleKeyword();
case End:
return endKeyword();
case Left:
return leftKeyword();
case Right:
return rightKeyword();
default:
ASSERT_NOT_REACHED();
return emptyString();
}
}
void VTTCue::setAlign(const String& value, ExceptionState& exceptionState)
{
CueAlignment alignment = m_cueAlignment;
if (value == startKeyword())
alignment = Start;
else if (value == middleKeyword())
alignment = Middle;
else if (value == endKeyword())
alignment = End;
else if (value == leftKeyword())
alignment = Left;
else if (value == rightKeyword())
alignment = Right;
else
exceptionState.throwDOMException(SyntaxError, "The value provided ('" + value + "') is invalid. Only 'start', 'middle', 'end', 'left', and 'right' are accepted.");
if (alignment == m_cueAlignment)
return;
cueWillChange();
m_cueAlignment = alignment;
cueDidChange();
}
void VTTCue::setText(const String& text)
{
if (m_text == text)
return;
cueWillChange();
m_vttNodeTree = nullptr;
m_text = text;
cueDidChange();
}
void VTTCue::createVTTNodeTree()
{
if (!m_vttNodeTree)
m_vttNodeTree = VTTParser::createDocumentFragmentFromCueText(document(), m_text);
}
void VTTCue::copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* parent)
{
for (Node* node = vttNode->firstChild(); node; node = node->nextSibling()) {
RefPtr<Node> clonedNode;
if (node->isVTTElement())
clonedNode = toVTTElement(node)->createEquivalentHTMLElement(document());
else
clonedNode = node->cloneNode(false);
parent->appendChild(clonedNode);
if (node->isContainerNode())
copyVTTNodeToDOMTree(toContainerNode(node), toContainerNode(clonedNode));
}
}
PassRefPtr<DocumentFragment> VTTCue::getCueAsHTML()
{
createVTTNodeTree();
RefPtr<DocumentFragment> clonedFragment = DocumentFragment::create(document());
copyVTTNodeToDOMTree(m_vttNodeTree.get(), clonedFragment.get());
return clonedFragment.release();
}
PassRefPtr<DocumentFragment> VTTCue::createCueRenderingTree()
{
RefPtr<DocumentFragment> clonedFragment;
createVTTNodeTree();
clonedFragment = DocumentFragment::create(document());
m_vttNodeTree->cloneChildNodes(clonedFragment.get());
return clonedFragment.release();
}
void VTTCue::setRegionId(const String& regionId)
{
if (m_regionId == regionId)
return;
cueWillChange();
m_regionId = regionId;
cueDidChange();
}
void VTTCue::notifyRegionWhenRemovingDisplayTree(bool notifyRegion)
{
m_notifyRegion = notifyRegion;
}
int VTTCue::calculateComputedLinePosition()
{
if (m_linePosition != undefinedPosition)
return m_linePosition;
if (!m_snapToLines)
return 100;
if (!track())
return -1;
int n = track()->trackIndexRelativeToRenderedTracks();
n++;
n = -n;
return n;
}
class VTTTextRunIterator : public TextRunIterator {
public:
VTTTextRunIterator() { }
VTTTextRunIterator(const TextRun* textRun, unsigned offset) : TextRunIterator(textRun, offset) { }
bool atParagraphSeparator() const
{
return WTF::Unicode::category(current()) & WTF::Unicode::Separator_Paragraph;
}
};
static TextDirection determineDirectionality(const String& value, bool& hasStrongDirectionality)
{
TextRun run(value);
BidiResolver<VTTTextRunIterator, BidiCharacterRun> bidiResolver;
bidiResolver.setStatus(BidiStatus(LTR, false));
bidiResolver.setPositionIgnoringNestedIsolates(VTTTextRunIterator(&run, 0));
return bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality);
}
static CSSValueID determineTextDirection(DocumentFragment* vttRoot)
{
DEFINE_STATIC_LOCAL(const String, rtTag, ("rt"));
ASSERT(vttRoot);
TextDirection textDirection = LTR;
for (Node* node = vttRoot->firstChild(); node; node = NodeTraversal::next(*node, vttRoot)) {
if (!node->isTextNode() || node->localName() == rtTag)
continue;
bool hasStrongDirectionality;
textDirection = determineDirectionality(node->nodeValue(), hasStrongDirectionality);
if (hasStrongDirectionality)
break;
}
return isLeftToRightDirection(textDirection) ? CSSValueLtr : CSSValueRtl;
}
void VTTCue::calculateDisplayParameters()
{
createVTTNodeTree();
m_displayDirection = determineTextDirection(m_vttNodeTree.get());
int maximumSize = m_textPosition;
if ((m_writingDirection == Horizontal && m_cueAlignment == Start && m_displayDirection == CSSValueLtr)
|| (m_writingDirection == Horizontal && m_cueAlignment == End && m_displayDirection == CSSValueRtl)
|| (m_writingDirection == Horizontal && m_cueAlignment == Left)
|| (m_writingDirection == VerticalGrowingLeft && (m_cueAlignment == Start || m_cueAlignment == Left))
|| (m_writingDirection == VerticalGrowingRight && (m_cueAlignment == Start || m_cueAlignment == Left))) {
maximumSize = 100 - m_textPosition;
} else if ((m_writingDirection == Horizontal && m_cueAlignment == End && m_displayDirection == CSSValueLtr)
|| (m_writingDirection == Horizontal && m_cueAlignment == Start && m_displayDirection == CSSValueRtl)
|| (m_writingDirection == Horizontal && m_cueAlignment == Right)
|| (m_writingDirection == VerticalGrowingLeft && (m_cueAlignment == End || m_cueAlignment == Right))
|| (m_writingDirection == VerticalGrowingRight && (m_cueAlignment == End || m_cueAlignment == Right))) {
maximumSize = m_textPosition;
} else if (m_cueAlignment == Middle) {
maximumSize = m_textPosition <= 50 ? m_textPosition : (100 - m_textPosition);
maximumSize = maximumSize * 2;
} else {
ASSERT_NOT_REACHED();
}
m_displaySize = std::min(m_cueSize, maximumSize);
if (m_writingDirection == Horizontal) {
switch (m_cueAlignment) {
case Start:
if (m_displayDirection == CSSValueLtr)
m_displayPosition.first = m_textPosition;
else
m_displayPosition.first = 100 - m_textPosition - m_displaySize;
break;
case End:
if (m_displayDirection == CSSValueRtl)
m_displayPosition.first = 100 - m_textPosition;
else
m_displayPosition.first = m_textPosition - m_displaySize;
break;
case Left:
if (m_displayDirection == CSSValueLtr)
m_displayPosition.first = m_textPosition;
else
m_displayPosition.first = 100 - m_textPosition;
break;
case Right:
if (m_displayDirection == CSSValueLtr)
m_displayPosition.first = m_textPosition - m_displaySize;
else
m_displayPosition.first = 100 - m_textPosition - m_displaySize;
break;
case Middle:
if (m_displayDirection == CSSValueLtr)
m_displayPosition.first = m_textPosition - m_displaySize / 2;
else
m_displayPosition.first = 100 - m_textPosition - m_displaySize / 2;
break;
case NumberOfAlignments:
ASSERT_NOT_REACHED();
}
} else {
switch (m_cueAlignment) {
case Start:
case Left:
m_displayPosition.second = m_textPosition;
break;
case End:
case Right:
m_displayPosition.second = m_textPosition - m_displaySize;
break;
case Middle:
m_displayPosition.second = m_textPosition - m_displaySize / 2;
break;
case NumberOfAlignments:
ASSERT_NOT_REACHED();
}
}
m_computedLinePosition = calculateComputedLinePosition();
if (m_snapToLines && m_displayPosition.second == undefinedPosition && m_writingDirection == Horizontal)
m_displayPosition.second = 0;
if (!m_snapToLines && m_displayPosition.second == undefinedPosition && m_writingDirection == Horizontal)
m_displayPosition.second = m_computedLinePosition;
if (m_snapToLines && m_displayPosition.first == undefinedPosition
&& (m_writingDirection == VerticalGrowingLeft || m_writingDirection == VerticalGrowingRight))
m_displayPosition.first = 0;
if (!m_snapToLines && (m_writingDirection == VerticalGrowingLeft || m_writingDirection == VerticalGrowingRight))
m_displayPosition.first = m_computedLinePosition;
}
void VTTCue::markFutureAndPastNodes(ContainerNode* root, double previousTimestamp, double movieTime)
{
DEFINE_STATIC_LOCAL(const String, timestampTag, ("timestamp"));
bool isPastNode = true;
double currentTimestamp = previousTimestamp;
if (currentTimestamp > movieTime)
isPastNode = false;
for (Node* child = root->firstChild(); child; child = NodeTraversal::next(*child, root)) {
if (child->nodeName() == timestampTag) {
double currentTimestamp;
bool check = VTTParser::collectTimeStamp(child->nodeValue(), currentTimestamp);
ASSERT_UNUSED(check, check);
if (currentTimestamp > movieTime)
isPastNode = false;
}
if (child->isVTTElement()) {
toVTTElement(child)->setIsPastNode(isPastNode);
if (!id().isEmpty())
toElement(child)->setIdAttribute(id());
}
}
}
void VTTCue::updateDisplayTree(double movieTime)
{
if (!track()->isRendered())
return;
m_cueBackgroundBox->removeChildren();
RefPtr<DocumentFragment> referenceTree = createCueRenderingTree();
markFutureAndPastNodes(referenceTree.get(), startTime(), movieTime);
m_cueBackgroundBox->appendChild(referenceTree, ASSERT_NO_EXCEPTION);
}
PassRefPtr<VTTCueBox> VTTCue::getDisplayTree(const IntSize& videoSize)
{
RefPtr<VTTCueBox> displayTree = displayTreeInternal();
if (!m_displayTreeShouldChange || !track()->isRendered())
return displayTree;
calculateDisplayParameters();
displayTree->removeChildren();
m_cueBackgroundBox->setShadowPseudoId(cueShadowPseudoId());
displayTree->appendChild(m_cueBackgroundBox);
displayTree->applyCSSProperties(videoSize);
m_displayTreeShouldChange = false;
return displayTree;
}
void VTTCue::removeDisplayTree()
{
if (m_notifyRegion && track()->regions()) {
VTTRegion* region = track()->regions()->getRegionById(m_regionId);
if (region)
region->willRemoveVTTCueBox(m_displayTree.get());
}
displayTreeInternal()->remove(ASSERT_NO_EXCEPTION);
}
void VTTCue::updateDisplay(const IntSize& videoSize, HTMLDivElement& container)
{
RefPtr<VTTCueBox> displayBox = getDisplayTree(videoSize);
VTTRegion* region = 0;
if (track()->regions())
region = track()->regions()->getRegionById(regionId());
if (!region) {
if (displayBox->hasChildren() && !container.contains(displayBox.get())) {
container.appendChild(displayBox);
}
} else {
RefPtr<HTMLDivElement> regionNode = region->getDisplayTree(document());
if (!container.contains(regionNode.get()))
container.appendChild(regionNode);
region->appendVTTCueBox(displayBox);
}
}
std::pair<double, double> VTTCue::getPositionCoordinates() const
{
std::pair<double, double> coordinates;
if (m_writingDirection == Horizontal && m_displayDirection == CSSValueLtr) {
coordinates.first = m_textPosition;
coordinates.second = m_computedLinePosition;
return coordinates;
}
if (m_writingDirection == Horizontal && m_displayDirection == CSSValueRtl) {
coordinates.first = 100 - m_textPosition;
coordinates.second = m_computedLinePosition;
return coordinates;
}
if (m_writingDirection == VerticalGrowingLeft) {
coordinates.first = 100 - m_computedLinePosition;
coordinates.second = m_textPosition;
return coordinates;
}
if (m_writingDirection == VerticalGrowingRight) {
coordinates.first = m_computedLinePosition;
coordinates.second = m_textPosition;
return coordinates;
}
ASSERT_NOT_REACHED();
return coordinates;
}
VTTCue::CueSetting VTTCue::settingName(VTTScanner& input)
{
CueSetting parsedSetting = None;
if (input.scan("vertical"))
parsedSetting = Vertical;
else if (input.scan("line"))
parsedSetting = Line;
else if (input.scan("position"))
parsedSetting = Position;
else if (input.scan("size"))
parsedSetting = Size;
else if (input.scan("align"))
parsedSetting = Align;
else if (RuntimeEnabledFeatures::webVTTRegionsEnabled() && input.scan("region"))
parsedSetting = RegionId;
if (parsedSetting != None && input.scan(':'))
return parsedSetting;
return None;
}
static bool scanPercentage(VTTScanner& input, const VTTScanner::Run& valueRun, int& number)
{
if (!input.scanDigits(number))
return false;
if (!input.scan('%') || !input.isAt(valueRun.end()))
return false;
return number >= 0 && number <= 100;
}
void VTTCue::parseSettings(const String& inputString)
{
VTTScanner input(inputString);
while (!input.isAtEnd()) {
input.skipWhile<VTTParser::isValidSettingDelimiter>();
if (input.isAtEnd())
break;
CueSetting name = settingName(input);
VTTScanner::Run valueRun = input.collectUntil<VTTParser::isValidSettingDelimiter>();
switch (name) {
case Vertical: {
if (input.scanRun(valueRun, verticalGrowingLeftKeyword()))
m_writingDirection = VerticalGrowingLeft;
else if (input.scanRun(valueRun, verticalGrowingRightKeyword()))
m_writingDirection = VerticalGrowingRight;
break;
}
case Line: {
bool isNegative = input.scan('-');
int linePosition;
unsigned numDigits = input.scanDigits(linePosition);
bool isPercentage = input.scan('%');
if (!input.isAt(valueRun.end()))
break;
if (!numDigits || (isPercentage && isNegative))
break;
if (isPercentage) {
if (linePosition < 0 || linePosition > 100)
break;
m_snapToLines = false;
} else {
if (isNegative)
linePosition = -linePosition;
m_snapToLines = true;
}
m_linePosition = linePosition;
break;
}
case Position: {
int number;
if (!scanPercentage(input, valueRun, number))
break;
m_textPosition = number;
break;
}
case Size: {
int number;
if (!scanPercentage(input, valueRun, number))
break;
m_cueSize = number;
break;
}
case Align: {
if (input.scanRun(valueRun, startKeyword()))
m_cueAlignment = Start;
else if (input.scanRun(valueRun, middleKeyword()))
m_cueAlignment = Middle;
else if (input.scanRun(valueRun, endKeyword()))
m_cueAlignment = End;
else if (input.scanRun(valueRun, leftKeyword()))
m_cueAlignment = Left;
else if (input.scanRun(valueRun, rightKeyword()))
m_cueAlignment = Right;
break;
}
case RegionId:
m_regionId = input.extractString(valueRun);
break;
case None:
break;
}
input.skipRun(valueRun);
}
if (m_regionId.isEmpty())
return;
if (m_linePosition != undefinedPosition || m_cueSize != 100 || m_writingDirection != Horizontal)
m_regionId = emptyString();
}
CSSValueID VTTCue::getCSSAlignment() const
{
return displayAlignmentMap[m_cueAlignment];
}
CSSValueID VTTCue::getCSSWritingDirection() const
{
return m_displayDirection;
}
CSSValueID VTTCue::getCSSWritingMode() const
{
return displayWritingModeMap[m_writingDirection];
}
int VTTCue::getCSSSize() const
{
ASSERT(m_displaySize != undefinedSize);
return m_displaySize;
}
std::pair<double, double> VTTCue::getCSSPosition() const
{
if (!m_snapToLines)
return getPositionCoordinates();
return m_displayPosition;
}
ExecutionContext* VTTCue::executionContext() const
{
ASSERT(m_cueBackgroundBox);
return m_cueBackgroundBox->executionContext();
}
Document& VTTCue::document() const
{
ASSERT(m_cueBackgroundBox);
return m_cueBackgroundBox->document();
}
}