From 7a1f777b9015b41fb7d2f7c8a60980338b046088 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 15 Feb 2018 18:48:22 +0000 Subject: [PATCH] Bug 1435989 - Add a 'ranges' attribute to the InspectorFontFace object, to expose ranges of text that were rendered with a specific font. r=bz,dholbert --- dom/base/nsRange.cpp | 9 +++--- dom/base/nsRange.h | 6 +++- dom/webidl/InspectorUtils.webidl | 19 +++++++++++- layout/base/nsLayoutUtils.cpp | 43 +++++++++++++++++--------- layout/base/nsLayoutUtils.h | 8 +++-- layout/inspector/InspectorFontFace.cpp | 12 +++++++ layout/inspector/InspectorFontFace.h | 10 ++++++ layout/inspector/InspectorUtils.cpp | 3 +- layout/inspector/InspectorUtils.h | 2 ++ 9 files changed, 88 insertions(+), 24 deletions(-) diff --git a/dom/base/nsRange.cpp b/dom/base/nsRange.cpp index 62e8df28c5a8..3ff2df531052 100644 --- a/dom/base/nsRange.cpp +++ b/dom/base/nsRange.cpp @@ -3473,7 +3473,8 @@ nsRange::GetClientRectsAndTexts( } nsresult -nsRange::GetUsedFontFaces(nsTArray>& aResult) +nsRange::GetUsedFontFaces(nsTArray>& aResult, + uint32_t aMaxRanges) { NS_ENSURE_TRUE(mStart.Container(), NS_ERROR_UNEXPECTED); @@ -3517,17 +3518,17 @@ nsRange::GetUsedFontFaces(nsTArray>& aResult) int32_t offset = startContainer == endContainer ? mEnd.Offset() : content->GetText()->GetLength(); nsLayoutUtils::GetFontFacesForText(frame, mStart.Offset(), offset, - true, fontFaces); + true, fontFaces, aMaxRanges); continue; } if (node == endContainer) { nsLayoutUtils::GetFontFacesForText(frame, 0, mEnd.Offset(), - true, fontFaces); + true, fontFaces, aMaxRanges); continue; } } - nsLayoutUtils::GetFontFacesForFrames(frame, fontFaces); + nsLayoutUtils::GetFontFacesForFrames(frame, fontFaces, aMaxRanges); } // Take ownership of the InspectorFontFaces in the table and move them into diff --git a/dom/base/nsRange.h b/dom/base/nsRange.h index 0895f3c0a708..f582b031b582 100644 --- a/dom/base/nsRange.h +++ b/dom/base/nsRange.h @@ -281,8 +281,12 @@ public: return parentNode; } + // aMaxRanges is the maximum number of text ranges to record for each face + // (pass 0 to just get the list of faces, without recording exact ranges + // where each face was used). nsresult GetUsedFontFaces( - nsTArray>& aResult); + nsTArray>& aResult, + uint32_t aMaxRanges); // nsIMutationObserver methods NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED diff --git a/dom/webidl/InspectorUtils.webidl b/dom/webidl/InspectorUtils.webidl index d5d435f5de04..8ae374e2efd7 100644 --- a/dom/webidl/InspectorUtils.webidl +++ b/dom/webidl/InspectorUtils.webidl @@ -64,7 +64,16 @@ namespace InspectorUtils { unsigned long long state, optional boolean clearActiveDocument = false); unsigned long long getContentState(Element element); - [NewObject, Throws] sequence getUsedFontFaces(Range range); + + // Get the font face(s) actually used to render the text in /range/, + // as a collection of InspectorFontFace objects (below). + // If /maxRanges/ is greater than zero, each InspectorFontFace will record + // up to /maxRanges/ fragments of content that used the face, for the caller + // to access via its .ranges attribute. + [NewObject, Throws] sequence getUsedFontFaces( + Range range, + optional unsigned long maxRanges = 0); + sequence getCSSPseudoElementNames(); void addPseudoClassLock(Element element, DOMString pseudoClass, @@ -135,6 +144,14 @@ interface InspectorFontFace { [NewObject,Throws] sequence getVariationInstances(); [NewObject,Throws] sequence getFeatures(); + // A list of Ranges of text rendered with this face. + // This will list the first /maxRanges/ ranges found when InspectorUtils.getUsedFontFaces + // was called (so it will be empty unless a non-zero maxRanges argument was passed). + // Note that this indicates how the document was rendered at the time of calling + // getUsedFontFaces; it does not reflect any subsequent modifications, so if styles + // have been modified since calling getUsedFontFaces, it may no longer be accurate. + [Constant,Cached] readonly attribute sequence ranges; + // meaningful only when the font is a user font defined using @font-face readonly attribute CSSFontFaceRule? rule; // null if no associated @font-face rule readonly attribute long srcIndex; // index in the rule's src list, -1 if no @font-face rule diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index ebb502e5dcdc..d2379f1b4ac1 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -8033,14 +8033,15 @@ nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot) static void GetFontFacesForFramesInner(nsIFrame* aFrame, - nsLayoutUtils::UsedFontFaceTable& aFontFaces) + nsLayoutUtils::UsedFontFaceTable& aFontFaces, + uint32_t aMaxRanges) { NS_PRECONDITION(aFrame, "NULL frame pointer"); if (aFrame->IsTextFrame()) { if (!aFrame->GetPrevContinuation()) { nsLayoutUtils::GetFontFacesForText(aFrame, 0, INT32_MAX, true, - aFontFaces); + aFontFaces, aMaxRanges); } return; } @@ -8052,19 +8053,20 @@ GetFontFacesForFramesInner(nsIFrame* aFrame, for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) { nsIFrame* child = e.get(); child = nsPlaceholderFrame::GetRealFrameFor(child); - GetFontFacesForFramesInner(child, aFontFaces); + GetFontFacesForFramesInner(child, aFontFaces, aMaxRanges); } } } /* static */ nsresult nsLayoutUtils::GetFontFacesForFrames(nsIFrame* aFrame, - UsedFontFaceTable& aFontFaces) + UsedFontFaceTable& aFontFaces, + uint32_t aMaxRanges) { NS_PRECONDITION(aFrame, "NULL frame pointer"); while (aFrame) { - GetFontFacesForFramesInner(aFrame, aFontFaces); + GetFontFacesForFramesInner(aFrame, aFontFaces, aMaxRanges); aFrame = GetNextContinuationOrIBSplitSibling(aFrame); } @@ -8073,9 +8075,12 @@ nsLayoutUtils::GetFontFacesForFrames(nsIFrame* aFrame, static void AddFontsFromTextRun(gfxTextRun* aTextRun, + nsIContent* aContent, + gfxSkipCharsIterator& aSkipIter, uint32_t aOffset, uint32_t aLength, - nsLayoutUtils::UsedFontFaceTable& aFontFaces) + nsLayoutUtils::UsedFontFaceTable& aFontFaces, + uint32_t aMaxRanges) { gfxTextRun::Range range(aOffset, aOffset + aLength); gfxTextRun::GlyphRunIterator iter(aTextRun, range); @@ -8083,15 +8088,21 @@ AddFontsFromTextRun(gfxTextRun* aTextRun, gfxFontEntry *fe = iter.GetGlyphRun()->mFont->GetFontEntry(); // if we have already listed this face, just make sure the match type is // recorded - InspectorFontFace* existingFace = aFontFaces.Get(fe); - if (existingFace) { - existingFace->AddMatchType(iter.GetGlyphRun()->mMatchType); + InspectorFontFace* fontFace = aFontFaces.Get(fe); + if (fontFace) { + fontFace->AddMatchType(iter.GetGlyphRun()->mMatchType); } else { // A new font entry we haven't seen before - InspectorFontFace* ff = - new InspectorFontFace(fe, aTextRun->GetFontGroup(), - iter.GetGlyphRun()->mMatchType); - aFontFaces.Put(fe, ff); + fontFace = new InspectorFontFace(fe, aTextRun->GetFontGroup(), + iter.GetGlyphRun()->mMatchType); + aFontFaces.Put(fe, fontFace); + } + if (fontFace->RangeCount() < aMaxRanges) { + uint32_t start = aSkipIter.ConvertSkippedToOriginal(iter.GetStringStart()); + uint32_t end = aSkipIter.ConvertSkippedToOriginal(iter.GetStringEnd()); + RefPtr range; + nsRange::CreateRange(aContent, start, aContent, end, getter_AddRefs(range)); + fontFace->AddRange(range); } } } @@ -8101,7 +8112,8 @@ nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame, int32_t aStartOffset, int32_t aEndOffset, bool aFollowContinuations, - UsedFontFaceTable& aFontFaces) + UsedFontFaceTable& aFontFaces, + uint32_t aMaxRanges) { NS_PRECONDITION(aFrame, "NULL frame pointer"); @@ -8136,7 +8148,8 @@ nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame, uint32_t skipStart = iter.ConvertOriginalToSkipped(fstart); uint32_t skipEnd = iter.ConvertOriginalToSkipped(fend); - AddFontsFromTextRun(textRun, skipStart, skipEnd - skipStart, aFontFaces); + AddFontsFromTextRun(textRun, aFrame->GetContent(), iter, + skipStart, skipEnd - skipStart, aFontFaces, aMaxRanges); curr = next; } while (aFollowContinuations && curr); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 0cbcc85af338..7437178c69d1 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -2278,21 +2278,25 @@ public: /** * Adds all font faces used in the frame tree starting from aFrame * to the list aFontFaceList. + * aMaxRanges: maximum number of text ranges to record for each face. */ static nsresult GetFontFacesForFrames(nsIFrame* aFrame, - UsedFontFaceTable& aResult); + UsedFontFaceTable& aResult, + uint32_t aMaxRanges); /** * Adds all font faces used within the specified range of text in aFrame, * and optionally its continuations, to the list in aFontFaceList. * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the * entire text is to be considered. + * aMaxRanges: maximum number of text ranges to record for each face. */ static nsresult GetFontFacesForText(nsIFrame* aFrame, int32_t aStartOffset, int32_t aEndOffset, bool aFollowContinuations, - UsedFontFaceTable& aResult); + UsedFontFaceTable& aResult, + uint32_t aMaxRanges); /** * Walks the frame tree starting at aFrame looking for textRuns. diff --git a/layout/inspector/InspectorFontFace.cpp b/layout/inspector/InspectorFontFace.cpp index fe2e07f8bd7c..a70a4fe8ff7f 100644 --- a/layout/inspector/InspectorFontFace.cpp +++ b/layout/inspector/InspectorFontFace.cpp @@ -294,5 +294,17 @@ InspectorFontFace::GetFeatures(nsTArray& aResult, } } +void +InspectorFontFace::GetRanges(nsTArray>& aResult) +{ + aResult = mRanges; +} + +void +InspectorFontFace::AddRange(nsRange* aRange) +{ + mRanges.AppendElement(aRange); +} + } // namespace dom } // namespace mozilla diff --git a/layout/inspector/InspectorFontFace.h b/layout/inspector/InspectorFontFace.h index 2b27d7d21fca..776e79e2a7e6 100644 --- a/layout/inspector/InspectorFontFace.h +++ b/layout/inspector/InspectorFontFace.h @@ -9,6 +9,7 @@ #include "mozilla/dom/InspectorUtilsBinding.h" #include "mozilla/dom/NonRefcountedDOMObject.h" +#include "nsRange.h" class gfxFontEntry; class gfxFontGroup; @@ -42,6 +43,11 @@ public: gfxFontEntry* GetFontEntry() const { return mFontEntry; } void AddMatchType(uint8_t aMatchType) { mMatchType |= aMatchType; } + void AddRange(nsRange* aRange); + size_t RangeCount() const { + return mRanges.Length(); + } + // Web IDL bool FromFontGroup(); bool FromLanguagePrefs(); @@ -62,6 +68,8 @@ public: void GetFeatures(nsTArray& aResult, ErrorResult& aRV); + void GetRanges(nsTArray>& aResult); + bool WrapObject(JSContext* aCx, JS::Handle aGivenProto, JS::MutableHandle aReflector) @@ -73,6 +81,8 @@ protected: RefPtr mFontEntry; RefPtr mFontGroup; uint8_t mMatchType; + + nsTArray> mRanges; }; } // namespace dom diff --git a/layout/inspector/InspectorUtils.cpp b/layout/inspector/InspectorUtils.cpp index f9fff700c795..3bd4b2b19c23 100644 --- a/layout/inspector/InspectorUtils.cpp +++ b/layout/inspector/InspectorUtils.cpp @@ -1030,10 +1030,11 @@ InspectorUtils::GetCleanStyleContextForElement(dom::Element* aElement, /* static */ void InspectorUtils::GetUsedFontFaces(GlobalObject& aGlobalObject, nsRange& aRange, + uint32_t aMaxRanges, nsTArray>& aResult, ErrorResult& aRv) { - nsresult rv = aRange.GetUsedFontFaces(aResult); + nsresult rv = aRange.GetUsedFontFaces(aResult, aMaxRanges); if (NS_FAILED(rv)) { aRv.Throw(rv); } diff --git a/layout/inspector/InspectorUtils.h b/layout/inspector/InspectorUtils.h index 16c96562c0f1..407fca44650c 100644 --- a/layout/inspector/InspectorUtils.h +++ b/layout/inspector/InspectorUtils.h @@ -222,6 +222,8 @@ public: static void GetUsedFontFaces(GlobalObject& aGlobal, nsRange& aRange, + uint32_t aMaxRanges, // max number of ranges to + // record for each face nsTArray>& aResult, ErrorResult& aRv);