TextTrackCue.h (8863B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 et tw=78: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_TextTrackCue_h 8 #define mozilla_dom_TextTrackCue_h 9 10 #include "mozilla/DOMEventTargetHelper.h" 11 #include "mozilla/StateWatching.h" 12 #include "mozilla/StaticPtr.h" 13 #include "mozilla/dom/DocumentFragment.h" 14 #include "mozilla/dom/HTMLDivElement.h" 15 #include "mozilla/dom/TextTrack.h" 16 #include "mozilla/dom/VTTCueBinding.h" 17 #include "nsCycleCollectionParticipant.h" 18 #include "nsIWebVTTParserWrapper.h" 19 20 namespace mozilla::dom { 21 22 class Document; 23 class HTMLTrackElement; 24 class TextTrackRegion; 25 26 class TextTrackCue final : public DOMEventTargetHelper { 27 public: 28 NS_DECL_ISUPPORTS_INHERITED 29 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrackCue, DOMEventTargetHelper) 30 31 // TextTrackCue WebIDL 32 // See bug 868509 about splitting out the WebVTT-specific interfaces. 33 static already_AddRefed<TextTrackCue> Constructor(GlobalObject& aGlobal, 34 double aStartTime, 35 double aEndTime, 36 const nsAString& aText, 37 ErrorResult& aRv) { 38 nsCOMPtr<nsPIDOMWindowInner> window = 39 do_QueryInterface(aGlobal.GetAsSupports()); 40 RefPtr<TextTrackCue> ttcue = 41 new TextTrackCue(window, aStartTime, aEndTime, aText, aRv); 42 return ttcue.forget(); 43 } 44 TextTrackCue(nsPIDOMWindowInner* aGlobal, double aStartTime, double aEndTime, 45 const nsAString& aText, ErrorResult& aRv); 46 47 TextTrackCue(nsPIDOMWindowInner* aGlobal, double aStartTime, double aEndTime, 48 const nsAString& aText, HTMLTrackElement* aTrackElement, 49 ErrorResult& aRv); 50 51 JSObject* WrapObject(JSContext* aCx, 52 JS::Handle<JSObject*> aGivenProto) override; 53 54 TextTrack* GetTrack() const { return mTrack; } 55 56 void GetId(nsAString& aId) const { aId = mId; } 57 58 void SetId(const nsAString& aId) { 59 if (mId == aId) { 60 return; 61 } 62 63 mId = aId; 64 } 65 66 double StartTime() const { return mStartTime; } 67 68 void SetStartTime(double aStartTime) { 69 if (mStartTime == aStartTime) { 70 return; 71 } 72 73 mStartTime = aStartTime; 74 mReset = true; 75 NotifyCueUpdated(this); 76 } 77 78 double EndTime() const { return mEndTime; } 79 80 void SetEndTime(double aEndTime) { 81 if (mEndTime == aEndTime) { 82 return; 83 } 84 85 mEndTime = aEndTime; 86 mReset = true; 87 NotifyCueUpdated(this); 88 } 89 90 bool PauseOnExit() { return mPauseOnExit; } 91 92 void SetPauseOnExit(bool aPauseOnExit) { 93 if (mPauseOnExit == aPauseOnExit) { 94 return; 95 } 96 97 mPauseOnExit = aPauseOnExit; 98 NotifyCueUpdated(nullptr); 99 } 100 101 TextTrackRegion* GetRegion(); 102 void SetRegion(TextTrackRegion* aRegion); 103 104 DirectionSetting Vertical() const { return mVertical; } 105 106 void SetVertical(const DirectionSetting& aVertical) { 107 if (mVertical == aVertical) { 108 return; 109 } 110 111 mReset = true; 112 mVertical = aVertical; 113 } 114 115 bool SnapToLines() { return mSnapToLines; } 116 117 void SetSnapToLines(bool aSnapToLines) { 118 if (mSnapToLines == aSnapToLines) { 119 return; 120 } 121 122 mReset = true; 123 mSnapToLines = aSnapToLines; 124 } 125 126 void GetLine(OwningDoubleOrAutoKeyword& aLine) const { 127 if (mLineIsAutoKeyword) { 128 aLine.SetAsAutoKeyword() = AutoKeyword::Auto; 129 return; 130 } 131 aLine.SetAsDouble() = mLine; 132 } 133 134 void SetLine(const DoubleOrAutoKeyword& aLine) { 135 if (aLine.IsDouble() && 136 (mLineIsAutoKeyword || (aLine.GetAsDouble() != mLine))) { 137 mLineIsAutoKeyword = false; 138 mLine = aLine.GetAsDouble(); 139 mReset = true; 140 return; 141 } 142 if (aLine.IsAutoKeyword() && !mLineIsAutoKeyword) { 143 mLineIsAutoKeyword = true; 144 mReset = true; 145 } 146 } 147 148 LineAlignSetting LineAlign() const { return mLineAlign; } 149 150 void SetLineAlign(LineAlignSetting& aLineAlign, ErrorResult& aRv) { 151 if (mLineAlign == aLineAlign) { 152 return; 153 } 154 155 mReset = true; 156 mLineAlign = aLineAlign; 157 } 158 159 void GetPosition(OwningDoubleOrAutoKeyword& aPosition) const { 160 if (mPositionIsAutoKeyword) { 161 aPosition.SetAsAutoKeyword() = AutoKeyword::Auto; 162 return; 163 } 164 aPosition.SetAsDouble() = mPosition; 165 } 166 167 void SetPosition(const DoubleOrAutoKeyword& aPosition, ErrorResult& aRv) { 168 if (!aPosition.IsAutoKeyword() && 169 (aPosition.GetAsDouble() > 100.0 || aPosition.GetAsDouble() < 0.0)) { 170 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); 171 return; 172 } 173 174 if (aPosition.IsDouble() && 175 (mPositionIsAutoKeyword || (aPosition.GetAsDouble() != mPosition))) { 176 mPositionIsAutoKeyword = false; 177 mPosition = aPosition.GetAsDouble(); 178 mReset = true; 179 return; 180 } 181 182 if (aPosition.IsAutoKeyword() && !mPositionIsAutoKeyword) { 183 mPositionIsAutoKeyword = true; 184 mReset = true; 185 } 186 } 187 188 PositionAlignSetting PositionAlign() const { return mPositionAlign; } 189 190 void SetPositionAlign(PositionAlignSetting aPositionAlign, ErrorResult& aRv) { 191 if (mPositionAlign == aPositionAlign) { 192 return; 193 } 194 195 mReset = true; 196 mPositionAlign = aPositionAlign; 197 } 198 199 double Size() const { return mSize; } 200 201 void SetSize(double aSize, ErrorResult& aRv) { 202 if (mSize == aSize) { 203 return; 204 } 205 206 if (aSize < 0.0 || aSize > 100.0) { 207 aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); 208 return; 209 } 210 211 mReset = true; 212 mSize = aSize; 213 } 214 215 AlignSetting Align() const { return mAlign; } 216 217 void SetAlign(AlignSetting& aAlign) { 218 if (mAlign == aAlign) { 219 return; 220 } 221 222 mReset = true; 223 mAlign = aAlign; 224 } 225 226 void GetText(nsAString& aText) const { aText = mText; } 227 228 void SetText(const nsAString& aText) { 229 if (mText == aText) { 230 return; 231 } 232 233 mReset = true; 234 mText = aText; 235 } 236 237 IMPL_EVENT_HANDLER(enter) 238 IMPL_EVENT_HANDLER(exit) 239 240 HTMLDivElement* GetDisplayState() { 241 return static_cast<HTMLDivElement*>(mDisplayState.get()); 242 } 243 244 void SetDisplayState(HTMLDivElement* aDisplayState) { 245 mDisplayState = aDisplayState; 246 mReset = false; 247 } 248 249 void Reset() { mReset = true; } 250 251 bool HasBeenReset() { return mReset; } 252 253 double ComputedLine(); 254 double ComputedPosition(); 255 PositionAlignSetting ComputedPositionAlign(); 256 257 // Helper functions for implementation. 258 const nsAString& Id() const { return mId; } 259 260 void SetTrack(TextTrack* aTextTrack) { 261 mTrack = aTextTrack; 262 if (!mHaveStartedWatcher && aTextTrack) { 263 mHaveStartedWatcher = true; 264 mWatchManager.Watch(mReset, &TextTrackCue::NotifyDisplayStatesChanged); 265 } else if (mHaveStartedWatcher && !aTextTrack) { 266 mHaveStartedWatcher = false; 267 mWatchManager.Unwatch(mReset, &TextTrackCue::NotifyDisplayStatesChanged); 268 } 269 } 270 271 /** 272 * Produces a tree of anonymous content based on the tree of the processed 273 * cue text. 274 * 275 * Returns a DocumentFragment that is the head of the tree of anonymous 276 * content. 277 */ 278 already_AddRefed<DocumentFragment> GetCueAsHTML(); 279 280 void SetTrackElement(HTMLTrackElement* aTrackElement); 281 282 void SetActive(bool aActive); 283 284 bool GetActive() { return mActive; } 285 286 private: 287 ~TextTrackCue(); 288 289 void NotifyCueUpdated(TextTrackCue* aCue) { 290 if (mTrack) { 291 mTrack->NotifyCueUpdated(aCue); 292 } 293 } 294 295 void NotifyDisplayStatesChanged(); 296 297 void SetDefaultCueSettings(); 298 nsresult StashDocument(); 299 300 bool IsTextBaseDirectionLTR() const; 301 302 RefPtr<Document> mDocument; 303 nsString mText; 304 double mStartTime; 305 double mEndTime; 306 307 RefPtr<TextTrack> mTrack; 308 RefPtr<HTMLTrackElement> mTrackElement; 309 nsString mId; 310 double mPosition; 311 bool mPositionIsAutoKeyword; 312 PositionAlignSetting mPositionAlign; 313 double mSize; 314 bool mPauseOnExit; 315 bool mSnapToLines; 316 RefPtr<TextTrackRegion> mRegion; 317 DirectionSetting mVertical; 318 bool mLineIsAutoKeyword; 319 double mLine; 320 AlignSetting mAlign; 321 LineAlignSetting mLineAlign; 322 323 // Holds the computed DOM elements that represent the parsed cue text. 324 // http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state 325 RefPtr<nsGenericHTMLElement> mDisplayState; 326 // Tells whether or not we need to recompute mDisplayState. This is set 327 // anytime a property that relates to the display of the TextTrackCue is 328 // changed. 329 Watchable<bool> mReset; 330 331 bool mActive; 332 333 static StaticRefPtr<nsIWebVTTParserWrapper> sParserWrapper; 334 335 // Only start watcher after the cue has text track. 336 bool mHaveStartedWatcher; 337 WatchManager<TextTrackCue> mWatchManager; 338 }; 339 340 } // namespace mozilla::dom 341 342 #endif // mozilla_dom_TextTrackCue_h