mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
67e04cfead
- Bug 1236750 - Introduce a new unit type CSSTransformedLayerPixel. r=kats (4e9bba3d19) - Bug 1236750 - Add a ViewAs() overload for casting (with a justification) one typed matrix to another. r=kats (c48e143508) - Bug 1236750 - Add some specialized typedefs of Matrix4x4 to represent layer transform matrices. r=kats (cc50113c98) - Bug 1239300 - reject promise with null while creating imagebitmap from empty blob; r=smaug (bff7483bf1) - Bug 1233056 - Long tapping on a link will select a different link from the page r=tnikkel (3a727b33c1) - Bug 1245674. Null-check mGlobal before dereferencing it in one more place in Promise code. r=smaug (68cf5312dc) - Bug 1236750 - Use strongly-typed matrices to represent layer transforms in APZ code. r=kats (63931eb2a1) - Bug 1236750 - Add typed getters for layer transform matrices. r=kats (baef978fe1) - Bug 1147673 - Relax the ancestor transform assertion a little. r=kats (ec9ce47ba4) - Bug 1154161 Initialize WidgetQueryContentEvent::mReply r=smaug (6086291313) - Bug 1240921 - Use nsAutoTArray in nsStyleSet::RuleNodeWithReplacement. r=bz. (66f6823b46) - Bug 1229437 part 1 - Add a helper function to get the float containing block of a given frame. r=dbaron (72de452e5d) - Bug 1229437 part 2 - Reparent floats inside pulled ruby segment. r=dbaron (82cc44632d) - Bug 1229437 part 3 - Support iterating frames of RubyColumn. r=dholbert (5d43e7f6ff) - Bug 1229437 part 4 - Reparent floats inside pulled ruby column. r=dbaron (4c1a7ff20b) - Bug 1229437 part 5 - Add crashtests for this bug. r=dbaron (6afabe1604) - Bug 1229437 followup - Fix sign-compare error in RubyColumn::Iterator on CLOSED TREE. (e93453d00a) - Bug 1229437 followup 2 - Fix another sign-compare error in RubyColumn::Iterator on CLOSED TREE. (c0bf6a2a7b) - Bug 1229437 followup 3 - Fix a mistake in RubyColumn::Iterator::SkipUntilExistingFrame(). a=me (1ce408e194) - bits of Bug 1072150 - Use the opt-out for various sloppy consumers (29d97c59ca) - Make test_bug946632 compatible with asynchronous scrolling. (bug 1140293, r=mstange) (e975a8350c) - fix misspatch of 1072150 (a3e580fa4b) - Bug 686281 - Implement nsStyleImageLayers; r=dbaron (85bb33c8e6) - Bug 686281 - Rename *background* to *imagelayer*; r=dbaron. (36d90f112d) - Bug 1230034 part 4 - Make FramePropertyDescriptor to be a template. r=froydnj,dbaron (271cd19b6e) - Bug 1230034 part 5 - Convert all frame properties which use DeleteValue and ReleaseValue as destructor to be typesafe. r=dbaron (efc8d63c9d) - Bug 1230034 part 6 - Convert all frame properties which do not hold pointer to be typed. r=dbaron (b5541775f7) - Bug 1230034 part 7 - Convert nsIFrame::GenConProperty to be typed. r=dbaron (2b71527b2c) - Bug 1230034 part 8 - Convert frame properties which assert on destructor to be typed. r=dbaron (0f125a3414) - Bug 1230034 part 9 - Convert FrameLayerBuilder::LayerManagerDataProperty to be typed. r=dbaron (1147498c2f) - Bug 1230034 part 10 - Convert remaining frame properties to by typed and remove the unsafe declaring macro. r=dbaron (d59d94eac4) - Bug 1072501: Unmap file mapping on source surface destruction. r=jrmuizel (19fd63890a) - Bug 1235613 - Make gfxCriticalError/Note strings in gfx/ unique. r=jrmuizel (780c6ff862) - Bug 1247535 - Fix -Wunreachable-code warning in mfbt/Poison.cpp. r=froydnj (0e7cf60b6d) - Bug 1239479: Add comments to mfbt/XorShift128PlusRNG.h from the RNG's designer. DONTBUILD r=Waldo (bb674b07ce) - Add an assertion message to the assert-is-empty in LinkedList::~LinkedList, to indicate to users who hit it that it's the fault of the caller, not the fault of MFBT code. No bug, rs=froydnj (4cad80874c) - Bug 1221103 - Add a comment to nsIChannel::securityInfo noting that this info may appear on non-nsHttpChannels and how that may happen. r=bz IGNORE IDL (cd9cebc3f2) - Bug 1001765 - Make login credentials in Saved Passwords manager editable. r=MattN (09eec4f6f8) - Bug 1188478 - Add an Import button to the password manager to open the browser migrator. r=dolske (d1126a89fc) - Bug 1199382 - Rename some strings from "password" to "login" in preferences and the manager. r=markh (60638f5e2a) - Bug 1207733 - Update @disabled on the Remove Password button when selection changes. r=MattN (64ac9f22f6) - bits of 1124472 and 1166840 (26e2681183) - Bug 1219707 - fix argument passing to migration.js, r=jaws (55d332f5c6) - bug 1215657 - make AccessibleWrap::get_accSelection work with proxies=davidb (4e72111032) - fix missing telemetry entry (4fcfabb3e6) and follow-up API changes of TFF#493.
383 lines
13 KiB
C++
383 lines
13 KiB
C++
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/* Per-block-formatting-context manager of font size inflation for pan and zoom UI. */
|
|
|
|
#include "nsFontInflationData.h"
|
|
#include "FramePropertyTable.h"
|
|
#include "nsTextControlFrame.h"
|
|
#include "nsListControlFrame.h"
|
|
#include "nsComboboxControlFrame.h"
|
|
#include "nsHTMLReflowState.h"
|
|
#include "nsTextFrameUtils.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::layout;
|
|
|
|
NS_DECLARE_FRAME_PROPERTY_DELETABLE(FontInflationDataProperty,
|
|
nsFontInflationData)
|
|
|
|
/* static */ nsFontInflationData*
|
|
nsFontInflationData::FindFontInflationDataFor(const nsIFrame *aFrame)
|
|
{
|
|
// We have one set of font inflation data per block formatting context.
|
|
const nsIFrame *bfc = FlowRootFor(aFrame);
|
|
NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
|
|
"should have found a flow root");
|
|
|
|
return static_cast<nsFontInflationData*>(
|
|
bfc->Properties().Get(FontInflationDataProperty()));
|
|
}
|
|
|
|
/* static */ bool
|
|
nsFontInflationData::UpdateFontInflationDataISizeFor(const nsHTMLReflowState& aReflowState)
|
|
{
|
|
nsIFrame *bfc = aReflowState.frame;
|
|
NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
|
|
"should have been given a flow root");
|
|
FrameProperties bfcProps(bfc->Properties());
|
|
nsFontInflationData *data = static_cast<nsFontInflationData*>(
|
|
bfcProps.Get(FontInflationDataProperty()));
|
|
bool oldInflationEnabled;
|
|
nscoord oldNCAISize;
|
|
if (data) {
|
|
oldNCAISize = data->mNCAISize;
|
|
oldInflationEnabled = data->mInflationEnabled;
|
|
} else {
|
|
data = new nsFontInflationData(bfc);
|
|
bfcProps.Set(FontInflationDataProperty(), data);
|
|
oldNCAISize = -1;
|
|
oldInflationEnabled = true; /* not relevant */
|
|
}
|
|
|
|
data->UpdateISize(aReflowState);
|
|
|
|
if (oldInflationEnabled != data->mInflationEnabled)
|
|
return true;
|
|
|
|
return oldInflationEnabled &&
|
|
oldNCAISize != data->mNCAISize;
|
|
}
|
|
|
|
/* static */ void
|
|
nsFontInflationData::MarkFontInflationDataTextDirty(nsIFrame *aBFCFrame)
|
|
{
|
|
NS_ASSERTION(aBFCFrame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
|
|
"should have been given a flow root");
|
|
|
|
FrameProperties bfcProps(aBFCFrame->Properties());
|
|
nsFontInflationData *data = static_cast<nsFontInflationData*>(
|
|
bfcProps.Get(FontInflationDataProperty()));
|
|
if (data) {
|
|
data->MarkTextDirty();
|
|
}
|
|
}
|
|
|
|
nsFontInflationData::nsFontInflationData(nsIFrame *aBFCFrame)
|
|
: mBFCFrame(aBFCFrame)
|
|
, mNCAISize(0)
|
|
, mTextAmount(0)
|
|
, mTextThreshold(0)
|
|
, mInflationEnabled(false)
|
|
, mTextDirty(true)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Find the closest common ancestor between aFrame1 and aFrame2, except
|
|
* treating the parent of a frame as the first-in-flow of its parent (so
|
|
* the result doesn't change when breaking changes).
|
|
*
|
|
* aKnownCommonAncestor is a known common ancestor of both.
|
|
*/
|
|
static nsIFrame*
|
|
NearestCommonAncestorFirstInFlow(nsIFrame *aFrame1, nsIFrame *aFrame2,
|
|
nsIFrame *aKnownCommonAncestor)
|
|
{
|
|
aFrame1 = aFrame1->FirstInFlow();
|
|
aFrame2 = aFrame2->FirstInFlow();
|
|
aKnownCommonAncestor = aKnownCommonAncestor->FirstInFlow();
|
|
|
|
nsAutoTArray<nsIFrame*, 32> ancestors1, ancestors2;
|
|
for (nsIFrame *f = aFrame1; f != aKnownCommonAncestor;
|
|
(f = f->GetParent()) && (f = f->FirstInFlow())) {
|
|
ancestors1.AppendElement(f);
|
|
}
|
|
for (nsIFrame *f = aFrame2; f != aKnownCommonAncestor;
|
|
(f = f->GetParent()) && (f = f->FirstInFlow())) {
|
|
ancestors2.AppendElement(f);
|
|
}
|
|
|
|
nsIFrame *result = aKnownCommonAncestor;
|
|
uint32_t i1 = ancestors1.Length(),
|
|
i2 = ancestors2.Length();
|
|
while (i1-- != 0 && i2-- != 0) {
|
|
if (ancestors1[i1] != ancestors2[i2]) {
|
|
break;
|
|
}
|
|
result = ancestors1[i1];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static nscoord
|
|
ComputeDescendantISize(const nsHTMLReflowState& aAncestorReflowState,
|
|
nsIFrame *aDescendantFrame)
|
|
{
|
|
nsIFrame *ancestorFrame = aAncestorReflowState.frame->FirstInFlow();
|
|
if (aDescendantFrame == ancestorFrame) {
|
|
return aAncestorReflowState.ComputedISize();
|
|
}
|
|
|
|
AutoInfallibleTArray<nsIFrame*, 16> frames;
|
|
for (nsIFrame *f = aDescendantFrame; f != ancestorFrame;
|
|
f = f->GetParent()->FirstInFlow()) {
|
|
frames.AppendElement(f);
|
|
}
|
|
|
|
// This ignores the inline-size contributions made by scrollbars, though in
|
|
// reality we don't have any scrollbars on the sorts of devices on
|
|
// which we use font inflation, so it's not a problem. But it may
|
|
// occasionally cause problems when writing tests on desktop.
|
|
|
|
uint32_t len = frames.Length();
|
|
nsHTMLReflowState *reflowStates = static_cast<nsHTMLReflowState*>
|
|
(moz_xmalloc(sizeof(nsHTMLReflowState) * len));
|
|
nsPresContext *presContext = aDescendantFrame->PresContext();
|
|
for (uint32_t i = 0; i < len; ++i) {
|
|
const nsHTMLReflowState &parentReflowState =
|
|
(i == 0) ? aAncestorReflowState : reflowStates[i - 1];
|
|
nsIFrame *frame = frames[len - i - 1];
|
|
WritingMode wm = frame->GetWritingMode();
|
|
LogicalSize availSize = parentReflowState.ComputedSize(wm);
|
|
availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
|
|
MOZ_ASSERT(frame->GetParent()->FirstInFlow() ==
|
|
parentReflowState.frame->FirstInFlow(),
|
|
"bad logic in this function");
|
|
new (reflowStates + i) nsHTMLReflowState(presContext, parentReflowState,
|
|
frame, availSize);
|
|
}
|
|
|
|
MOZ_ASSERT(reflowStates[len - 1].frame == aDescendantFrame,
|
|
"bad logic in this function");
|
|
nscoord result = reflowStates[len - 1].ComputedISize();
|
|
|
|
for (uint32_t i = len; i-- != 0; ) {
|
|
reflowStates[i].~nsHTMLReflowState();
|
|
}
|
|
moz_free(reflowStates);
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
nsFontInflationData::UpdateISize(const nsHTMLReflowState &aReflowState)
|
|
{
|
|
nsIFrame *bfc = aReflowState.frame;
|
|
NS_ASSERTION(bfc->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT,
|
|
"must be block formatting context");
|
|
|
|
nsIFrame *firstInflatableDescendant =
|
|
FindEdgeInflatableFrameIn(bfc, eFromStart);
|
|
if (!firstInflatableDescendant) {
|
|
mTextAmount = 0;
|
|
mTextThreshold = 0; // doesn't matter
|
|
mTextDirty = false;
|
|
mInflationEnabled = false;
|
|
return;
|
|
}
|
|
nsIFrame *lastInflatableDescendant =
|
|
FindEdgeInflatableFrameIn(bfc, eFromEnd);
|
|
MOZ_ASSERT(!firstInflatableDescendant == !lastInflatableDescendant,
|
|
"null-ness should match; NearestCommonAncestorFirstInFlow"
|
|
" will crash when passed null");
|
|
|
|
// Particularly when we're computing for the root BFC, the inline-size of
|
|
// nca might differ significantly for the inline-size of bfc.
|
|
nsIFrame *nca = NearestCommonAncestorFirstInFlow(firstInflatableDescendant,
|
|
lastInflatableDescendant,
|
|
bfc);
|
|
while (!nca->IsContainerForFontSizeInflation()) {
|
|
nca = nca->GetParent()->FirstInFlow();
|
|
}
|
|
|
|
nscoord newNCAISize = ComputeDescendantISize(aReflowState, nca);
|
|
|
|
// See comment above "font.size.inflation.lineThreshold" in
|
|
// modules/libpref/src/init/all.js .
|
|
nsIPresShell* presShell = bfc->PresContext()->PresShell();
|
|
uint32_t lineThreshold = presShell->FontSizeInflationLineThreshold();
|
|
nscoord newTextThreshold = (newNCAISize * lineThreshold) / 100;
|
|
|
|
if (mTextThreshold <= mTextAmount && mTextAmount < newTextThreshold) {
|
|
// Because we truncate our scan when we hit sufficient text, we now
|
|
// need to rescan.
|
|
mTextDirty = true;
|
|
}
|
|
|
|
mNCAISize = newNCAISize;
|
|
mTextThreshold = newTextThreshold;
|
|
mInflationEnabled = mTextAmount >= mTextThreshold;
|
|
}
|
|
|
|
/* static */ nsIFrame*
|
|
nsFontInflationData::FindEdgeInflatableFrameIn(nsIFrame* aFrame,
|
|
SearchDirection aDirection)
|
|
{
|
|
// NOTE: This function has a similar structure to ScanTextIn!
|
|
|
|
// FIXME: Should probably only scan the text that's actually going to
|
|
// be inflated!
|
|
|
|
nsIFormControlFrame* fcf = do_QueryFrame(aFrame);
|
|
if (fcf) {
|
|
return aFrame;
|
|
}
|
|
|
|
// FIXME: aDirection!
|
|
nsAutoTArray<FrameChildList, 4> lists;
|
|
aFrame->GetChildLists(&lists);
|
|
for (uint32_t i = 0, len = lists.Length(); i < len; ++i) {
|
|
const nsFrameList& list =
|
|
lists[(aDirection == eFromStart) ? i : len - i - 1].mList;
|
|
for (nsIFrame *kid = (aDirection == eFromStart) ? list.FirstChild()
|
|
: list.LastChild();
|
|
kid;
|
|
kid = (aDirection == eFromStart) ? kid->GetNextSibling()
|
|
: kid->GetPrevSibling()) {
|
|
if (kid->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) {
|
|
// Goes in a different set of inflation data.
|
|
continue;
|
|
}
|
|
|
|
if (kid->GetType() == nsGkAtoms::textFrame) {
|
|
nsIContent *content = kid->GetContent();
|
|
if (content && kid == content->GetPrimaryFrame()) {
|
|
uint32_t len = nsTextFrameUtils::
|
|
ComputeApproximateLengthWithWhitespaceCompression(
|
|
content, kid->StyleText());
|
|
if (len != 0) {
|
|
return kid;
|
|
}
|
|
}
|
|
} else {
|
|
nsIFrame *kidResult =
|
|
FindEdgeInflatableFrameIn(kid, aDirection);
|
|
if (kidResult) {
|
|
return kidResult;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
nsFontInflationData::ScanText()
|
|
{
|
|
mTextDirty = false;
|
|
mTextAmount = 0;
|
|
ScanTextIn(mBFCFrame);
|
|
mInflationEnabled = mTextAmount >= mTextThreshold;
|
|
}
|
|
|
|
static uint32_t
|
|
DoCharCountOfLargestOption(nsIFrame *aContainer)
|
|
{
|
|
uint32_t result = 0;
|
|
for (nsIFrame* option : aContainer->PrincipalChildList()) {
|
|
uint32_t optionResult;
|
|
if (option->GetContent()->IsHTMLElement(nsGkAtoms::optgroup)) {
|
|
optionResult = DoCharCountOfLargestOption(option);
|
|
} else {
|
|
// REVIEW: Check the frame structure for this!
|
|
optionResult = 0;
|
|
for (nsIFrame* optionChild : option->PrincipalChildList()) {
|
|
if (optionChild->GetType() == nsGkAtoms::textFrame) {
|
|
optionResult += nsTextFrameUtils::
|
|
ComputeApproximateLengthWithWhitespaceCompression(
|
|
optionChild->GetContent(), optionChild->StyleText());
|
|
}
|
|
}
|
|
}
|
|
if (optionResult > result) {
|
|
result = optionResult;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static uint32_t
|
|
CharCountOfLargestOption(nsIFrame *aListControlFrame)
|
|
{
|
|
return DoCharCountOfLargestOption(
|
|
static_cast<nsListControlFrame*>(aListControlFrame)->GetOptionsContainer());
|
|
}
|
|
|
|
void
|
|
nsFontInflationData::ScanTextIn(nsIFrame *aFrame)
|
|
{
|
|
// NOTE: This function has a similar structure to FindEdgeInflatableFrameIn!
|
|
|
|
// FIXME: Should probably only scan the text that's actually going to
|
|
// be inflated!
|
|
|
|
nsIFrame::ChildListIterator lists(aFrame);
|
|
for (; !lists.IsDone(); lists.Next()) {
|
|
nsFrameList::Enumerator kids(lists.CurrentList());
|
|
for (; !kids.AtEnd(); kids.Next()) {
|
|
nsIFrame *kid = kids.get();
|
|
if (kid->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) {
|
|
// Goes in a different set of inflation data.
|
|
continue;
|
|
}
|
|
|
|
nsIAtom *fType = kid->GetType();
|
|
if (fType == nsGkAtoms::textFrame) {
|
|
nsIContent *content = kid->GetContent();
|
|
if (content && kid == content->GetPrimaryFrame()) {
|
|
uint32_t len = nsTextFrameUtils::
|
|
ComputeApproximateLengthWithWhitespaceCompression(
|
|
content, kid->StyleText());
|
|
if (len != 0) {
|
|
nscoord fontSize = kid->StyleFont()->mFont.size;
|
|
if (fontSize > 0) {
|
|
mTextAmount += fontSize * len;
|
|
}
|
|
}
|
|
}
|
|
} else if (fType == nsGkAtoms::textInputFrame) {
|
|
// We don't want changes to the amount of text in a text input
|
|
// to change what we count towards inflation.
|
|
nscoord fontSize = kid->StyleFont()->mFont.size;
|
|
int32_t charCount = static_cast<nsTextControlFrame*>(kid)->GetCols();
|
|
mTextAmount += charCount * fontSize;
|
|
} else if (fType == nsGkAtoms::comboboxControlFrame) {
|
|
// See textInputFrame above (with s/amount of text/selected option/).
|
|
// Don't just recurse down to the list control inside, since we
|
|
// need to exclude the display frame.
|
|
nscoord fontSize = kid->StyleFont()->mFont.size;
|
|
int32_t charCount = CharCountOfLargestOption(
|
|
static_cast<nsComboboxControlFrame*>(kid)->GetDropDown());
|
|
mTextAmount += charCount * fontSize;
|
|
} else if (fType == nsGkAtoms::listControlFrame) {
|
|
// See textInputFrame above (with s/amount of text/selected option/).
|
|
nscoord fontSize = kid->StyleFont()->mFont.size;
|
|
int32_t charCount = CharCountOfLargestOption(kid);
|
|
mTextAmount += charCount * fontSize;
|
|
} else {
|
|
// recursive step
|
|
ScanTextIn(kid);
|
|
}
|
|
|
|
if (mTextAmount >= mTextThreshold) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|