зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1330236 - Compute SVG getNumberOfChars() quicker in simple cases. r=longsonr+218550
MozReview-Commit-ID: FgwR9dxTefx --HG-- extra : rebase_source : 5b1ba3aa727cdd278a4b40c24231ca446b8bc45d
This commit is contained in:
Родитель
740cebbff8
Коммит
4f17cad8f0
|
@ -5,9 +5,14 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/SVGTextContentElement.h"
|
||||
#include "nsISVGPoint.h"
|
||||
#include "SVGTextFrame.h"
|
||||
|
||||
#include "mozilla/dom/SVGIRect.h"
|
||||
#include "nsBidiUtils.h"
|
||||
#include "nsISVGPoint.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsTextFrameUtils.h"
|
||||
#include "nsTextNode.h"
|
||||
#include "SVGTextFrame.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -32,14 +37,18 @@ SVGTextFrame*
|
|||
SVGTextContentElement::GetSVGTextFrame()
|
||||
{
|
||||
nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
|
||||
while (frame) {
|
||||
SVGTextFrame* textFrame = do_QueryFrame(frame);
|
||||
if (textFrame) {
|
||||
return textFrame;
|
||||
}
|
||||
frame = frame->GetParent();
|
||||
}
|
||||
return nullptr;
|
||||
nsIFrame* textFrame =
|
||||
nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::svgTextFrame);
|
||||
return static_cast<SVGTextFrame*>(textFrame);
|
||||
}
|
||||
|
||||
SVGTextFrame*
|
||||
SVGTextContentElement::GetSVGTextFrameForNonLayoutDependentQuery()
|
||||
{
|
||||
nsIFrame* frame = GetPrimaryFrame(FlushType::Frames);
|
||||
nsIFrame* textFrame =
|
||||
nsLayoutUtils::GetClosestFrameOfType(frame, nsGkAtoms::svgTextFrame);
|
||||
return static_cast<SVGTextFrame*>(textFrame);
|
||||
}
|
||||
|
||||
already_AddRefed<SVGAnimatedLength>
|
||||
|
@ -56,9 +65,62 @@ SVGTextContentElement::LengthAdjust()
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
static bool
|
||||
FragmentHasSkippableCharacter(const T* aBuffer, uint32_t aLength)
|
||||
{
|
||||
for (uint32_t i = 0; i < aLength; i++) {
|
||||
if (nsTextFrameUtils::IsSkippableCharacterForTransformText(aBuffer[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Maybe<int32_t>
|
||||
SVGTextContentElement::GetNonLayoutDependentNumberOfChars()
|
||||
{
|
||||
SVGTextFrame* frame = GetSVGTextFrameForNonLayoutDependentQuery();
|
||||
if (!frame || frame != GetPrimaryFrame()) {
|
||||
// Only support this fast path on <text>, not child <tspan>s, etc.
|
||||
return Some(0);
|
||||
}
|
||||
|
||||
uint32_t num = 0;
|
||||
|
||||
for (nsINode* n = Element::GetFirstChild(); n; n = n->GetNextSibling()) {
|
||||
if (!n->IsNodeOfType(nsINode::eTEXT)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const nsTextFragment* text = static_cast<nsTextNode*>(n)->GetText();
|
||||
uint32_t length = text->GetLength();
|
||||
|
||||
if (text->Is2b()) {
|
||||
if (FragmentHasSkippableCharacter(text->Get2b(), length)) {
|
||||
return Nothing();
|
||||
}
|
||||
} else {
|
||||
auto buffer = reinterpret_cast<const uint8_t*>(text->Get1b());
|
||||
if (FragmentHasSkippableCharacter(buffer, length)) {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
num += length;
|
||||
}
|
||||
|
||||
return Some(num);
|
||||
}
|
||||
|
||||
int32_t
|
||||
SVGTextContentElement::GetNumberOfChars()
|
||||
{
|
||||
Maybe<int32_t> num = GetNonLayoutDependentNumberOfChars();
|
||||
if (num) {
|
||||
return *num;
|
||||
}
|
||||
|
||||
SVGTextFrame* textFrame = GetSVGTextFrame();
|
||||
return textFrame ? textFrame->GetNumberOfChars(this) : 0;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ protected:
|
|||
{}
|
||||
|
||||
SVGTextFrame* GetSVGTextFrame();
|
||||
SVGTextFrame* GetSVGTextFrameForNonLayoutDependentQuery();
|
||||
mozilla::Maybe<int32_t> GetNonLayoutDependentNumberOfChars();
|
||||
|
||||
enum { LENGTHADJUST };
|
||||
virtual nsSVGEnum* EnumAttributes() = 0;
|
||||
|
|
|
@ -56,6 +56,36 @@ IsSpaceOrTabOrSegmentBreak(char16_t aCh)
|
|||
return IsSpaceOrTab(aCh) || IsSegmentBreak(aCh);
|
||||
}
|
||||
|
||||
template<typename CharT>
|
||||
/* static */ bool
|
||||
nsTextFrameUtils::IsSkippableCharacterForTransformText(CharT aChar)
|
||||
{
|
||||
return aChar == ' ' ||
|
||||
aChar == '\t' ||
|
||||
aChar == '\n' ||
|
||||
aChar == CH_SHY ||
|
||||
(aChar > 0xFF && IsBidiControl(aChar));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
template<typename CharT>
|
||||
static void AssertSkippedExpectedChars(const CharT* aText,
|
||||
const gfxSkipChars& aSkipChars,
|
||||
int32_t aSkipCharsOffset)
|
||||
{
|
||||
gfxSkipCharsIterator it(aSkipChars);
|
||||
it.AdvanceOriginal(aSkipCharsOffset);
|
||||
while (it.GetOriginalOffset() < it.GetOriginalEnd()) {
|
||||
CharT ch = aText[it.GetOriginalOffset() - aSkipCharsOffset];
|
||||
MOZ_ASSERT(!it.IsOriginalCharSkipped() ||
|
||||
nsTextFrameUtils::IsSkippableCharacterForTransformText(ch),
|
||||
"skipped unexpected character; need to update "
|
||||
"IsSkippableCharacterForTransformText?");
|
||||
it.AdvanceOriginal(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class CharT>
|
||||
static CharT*
|
||||
TransformWhiteSpaces(const CharT* aText, uint32_t aLength,
|
||||
|
@ -183,6 +213,9 @@ nsTextFrameUtils::TransformText(const CharT* aText, uint32_t aLength,
|
|||
{
|
||||
uint32_t flags = 0;
|
||||
CharT* outputStart = aOutput;
|
||||
#ifdef DEBUG
|
||||
int32_t skipCharsOffset = aSkipChars->GetOriginalCharCount();
|
||||
#endif
|
||||
|
||||
bool lastCharArabic = false;
|
||||
if (aCompression == COMPRESS_NONE ||
|
||||
|
@ -303,12 +336,18 @@ nsTextFrameUtils::TransformText(const CharT* aText, uint32_t aLength,
|
|||
flags |= TEXT_WAS_TRANSFORMED;
|
||||
}
|
||||
*aAnalysisFlags = flags;
|
||||
|
||||
#ifdef DEBUG
|
||||
AssertSkippedExpectedChars(aText, *aSkipChars, skipCharsOffset);
|
||||
#endif
|
||||
return aOutput;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This template is part of public API of nsTextFrameUtils, while
|
||||
* its function body is not available in the header. It may stop working
|
||||
* (fail to resolve symbol in link time) once its callsites are moved to a
|
||||
* NOTE: The TransformText and IsSkippableCharacterForTransformText template
|
||||
* functions are part of the public API of nsTextFrameUtils, while
|
||||
* their function bodies are not available in the header. They may stop working
|
||||
* (fail to resolve symbol in link time) once their callsites are moved to a
|
||||
* different translation unit (e.g. a different unified source file).
|
||||
* Explicit instantiating this function template with `uint8_t` and `char16_t`
|
||||
* could prevent us from the potential risk.
|
||||
|
@ -327,6 +366,10 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
|
|||
uint8_t* aIncomingFlags,
|
||||
gfxSkipChars* aSkipChars,
|
||||
uint32_t* aAnalysisFlags);
|
||||
template bool
|
||||
nsTextFrameUtils::IsSkippableCharacterForTransformText(uint8_t aChar);
|
||||
template bool
|
||||
nsTextFrameUtils::IsSkippableCharacterForTransformText(char16_t aChar);
|
||||
|
||||
uint32_t
|
||||
nsTextFrameUtils::ComputeApproximateLengthWithWhitespaceCompression(
|
||||
|
|
|
@ -121,6 +121,16 @@ public:
|
|||
gfxSkipChars* aSkipChars,
|
||||
uint32_t* aAnalysisFlags);
|
||||
|
||||
/**
|
||||
* Returns whether aChar is a character that nsTextFrameUtils::TransformText
|
||||
* might mark as skipped. This is used by
|
||||
* SVGTextContentElement::GetNumberOfChars to know whether reflowing frames,
|
||||
* so that we have the results of TransformText, is required, or whether we
|
||||
* can use a fast path instead.
|
||||
*/
|
||||
template<class CharT>
|
||||
static bool IsSkippableCharacterForTransformText(CharT aChar);
|
||||
|
||||
static void
|
||||
AppendLineBreakOffset(nsTArray<uint32_t>* aArray, uint32_t aOffset)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче