mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 14:25:52 +00:00
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
commit
486051b718
@ -50,7 +50,8 @@ tabbrowser {
|
||||
/* Needed to allow tabs to shrink to be skinnier than their page-title: */
|
||||
min-width: 0;
|
||||
}
|
||||
.scrollbox-innerbox {
|
||||
|
||||
.tabbrowser-arrowscrollbox > .arrowscrollbox-scrollbox > .scrollbox-innerbox {
|
||||
/* Needed to prevent tabstrip from growing as wide as the sum of the tabs'
|
||||
page-title widths (when we'd rather have it be as wide as the window and
|
||||
compress the tabs to their minimum size): */
|
||||
|
@ -1478,7 +1478,6 @@ nsIDocument::nsIDocument()
|
||||
mHasDisplayDocument(false),
|
||||
mFontFaceSetDirty(true),
|
||||
mGetUserFontSetCalled(false),
|
||||
mPostedFlushUserFontSet(false),
|
||||
mDidFireDOMContentLoaded(true),
|
||||
mHasScrollLinkedEffect(false),
|
||||
mFrameRequestCallbacksScheduled(false),
|
||||
@ -3993,8 +3992,11 @@ nsDocument::CreateShell(nsPresContext* aContext, nsViewManager* aViewManager,
|
||||
|
||||
UpdateFrameRequestCallbackSchedulingState();
|
||||
|
||||
// Now that we have a shell, we might have @font-face rules.
|
||||
RebuildUserFontSet();
|
||||
// Now that we have a shell, we might have @font-face rules (the presence of a
|
||||
// shell may change which rules apply to us). We don't need to do anything
|
||||
// like EnsureStyleFlush or such, there's nothing to update yet and when stuff
|
||||
// is ready to update we'll flush the font set.
|
||||
MarkUserFontSetDirty();
|
||||
|
||||
return shell.forget();
|
||||
}
|
||||
@ -4090,8 +4092,10 @@ nsDocument::DeleteShell()
|
||||
ImageTracker()->RequestDiscardAll();
|
||||
|
||||
// Now that we no longer have a shell, we need to forget about any FontFace
|
||||
// objects for @font-face rules that came from the style set.
|
||||
RebuildUserFontSet();
|
||||
// objects for @font-face rules that came from the style set. There's no need
|
||||
// to call EnsureStyleFlush either, the shell is going away anyway, so there's
|
||||
// no point on it.
|
||||
MarkUserFontSetDirty();
|
||||
|
||||
nsIPresShell* oldShell = mPresShell;
|
||||
mPresShell = nullptr;
|
||||
@ -12668,7 +12672,7 @@ nsIDocument::GetUserFontSet(bool aFlushUserFontSet)
|
||||
// we *never* build the user font set until the first call to
|
||||
// GetUserFontSet. However, once it's been requested, we can't wait
|
||||
// for somebody to call GetUserFontSet in order to rebuild it (see
|
||||
// comments below in RebuildUserFontSet for why).
|
||||
// comments below in MarkUserFontSetDirty for why).
|
||||
#ifdef DEBUG
|
||||
bool userFontSetGottenBefore = mGetUserFontSetCalled;
|
||||
#endif
|
||||
@ -12705,42 +12709,44 @@ nsIDocument::FlushUserFontSet()
|
||||
// does we'll create it.
|
||||
}
|
||||
|
||||
if (mFontFaceSetDirty) {
|
||||
if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
|
||||
nsTArray<nsFontFaceRuleContainer> rules;
|
||||
nsIPresShell* shell = GetShell();
|
||||
if (shell && !shell->StyleSet()->AppendFontFaceRules(rules)) {
|
||||
return;
|
||||
}
|
||||
if (!mFontFaceSetDirty) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
mFontFaceSetDirty = false;
|
||||
|
||||
if (!mFontFaceSet && !rules.IsEmpty()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
|
||||
mFontFaceSet = new FontFaceSet(window, this);
|
||||
}
|
||||
if (mFontFaceSet) {
|
||||
changed = mFontFaceSet->UpdateRules(rules);
|
||||
}
|
||||
|
||||
// We need to enqueue a style change reflow (for later) to
|
||||
// reflect that we're modifying @font-face rules. (However,
|
||||
// without a reflow, nothing will happen to start any downloads
|
||||
// that are needed.)
|
||||
if (changed && shell) {
|
||||
nsPresContext* presContext = shell->GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->UserFontSetUpdated();
|
||||
}
|
||||
}
|
||||
if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
|
||||
nsTArray<nsFontFaceRuleContainer> rules;
|
||||
nsIPresShell* shell = GetShell();
|
||||
if (shell && !shell->StyleSet()->AppendFontFaceRules(rules)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFontFaceSetDirty = false;
|
||||
|
||||
if (!mFontFaceSet && !rules.IsEmpty()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetScopeObject());
|
||||
mFontFaceSet = new FontFaceSet(window, this);
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
if (mFontFaceSet) {
|
||||
changed = mFontFaceSet->UpdateRules(rules);
|
||||
}
|
||||
|
||||
// We need to enqueue a style change reflow (for later) to
|
||||
// reflect that we're modifying @font-face rules. (However,
|
||||
// without a reflow, nothing will happen to start any downloads
|
||||
// that are needed.)
|
||||
if (changed && shell) {
|
||||
if (nsPresContext* presContext = shell->GetPresContext()) {
|
||||
presContext->UserFontSetUpdated();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIDocument::RebuildUserFontSet()
|
||||
nsIDocument::MarkUserFontSetDirty()
|
||||
{
|
||||
if (!mGetUserFontSetCalled) {
|
||||
// We want to lazily build the user font set the first time it's
|
||||
@ -12750,27 +12756,6 @@ nsIDocument::RebuildUserFontSet()
|
||||
}
|
||||
|
||||
mFontFaceSetDirty = true;
|
||||
if (nsIPresShell* shell = GetShell()) {
|
||||
shell->SetNeedStyleFlush();
|
||||
}
|
||||
|
||||
// Somebody has already asked for the user font set, so we need to
|
||||
// post an event to rebuild it. Setting the user font set to be dirty
|
||||
// and lazily rebuilding it isn't sufficient, since it is only the act
|
||||
// of rebuilding it that will trigger the style change reflow that
|
||||
// calls GetUserFontSet. (This reflow causes rebuilding of text runs,
|
||||
// which starts font loads, whose completion causes another style
|
||||
// change reflow).
|
||||
if (!mPostedFlushUserFontSet) {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
NewRunnableMethod("nsIDocument::HandleRebuildUserFontSet",
|
||||
this,
|
||||
&nsIDocument::HandleRebuildUserFontSet);
|
||||
if (NS_SUCCEEDED(Dispatch(TaskCategory::Other, ev.forget()))) {
|
||||
mPostedFlushUserFontSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontFaceSet*
|
||||
|
@ -3071,7 +3071,7 @@ public:
|
||||
|
||||
gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
|
||||
void FlushUserFontSet();
|
||||
void RebuildUserFontSet(); // asynchronously
|
||||
void MarkUserFontSetDirty();
|
||||
mozilla::dom::FontFaceSet* GetFonts() { return mFontFaceSet; }
|
||||
|
||||
// FontFaceSource
|
||||
@ -3289,11 +3289,6 @@ protected:
|
||||
|
||||
mozilla::dom::XPathEvaluator* XPathEvaluator();
|
||||
|
||||
void HandleRebuildUserFontSet() {
|
||||
mPostedFlushUserFontSet = false;
|
||||
FlushUserFontSet();
|
||||
}
|
||||
|
||||
// Update our frame request callback scheduling state, if needed. This will
|
||||
// schedule or unschedule them, if necessary, and update
|
||||
// mFrameRequestCallbacksScheduled. aOldShell should only be passed when
|
||||
@ -3543,9 +3538,6 @@ protected:
|
||||
// Has GetUserFontSet() been called?
|
||||
bool mGetUserFontSetCalled : 1;
|
||||
|
||||
// Do we currently have an event posted to call FlushUserFontSet?
|
||||
bool mPostedFlushUserFontSet : 1;
|
||||
|
||||
// True if we have fired the DOMContentLoaded event, or don't plan to fire one
|
||||
// (e.g. we're not being parsed at all).
|
||||
bool mDidFireDOMContentLoaded : 1;
|
||||
|
@ -484,7 +484,7 @@ UnscaledFontFontconfig::GetWRFontDescriptor(WRFontDescriptorOutput aCb, void* aB
|
||||
|
||||
const char* path = mFile.c_str();
|
||||
size_t pathLength = strlen(path);
|
||||
aCb(reinterpret_cast<const uint8_t*>(path), pathLength, 0, aBaton);
|
||||
aCb(reinterpret_cast<const uint8_t*>(path), pathLength, mIndex, aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ UnscaledFontFreeType::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
|
||||
|
||||
const char* path = mFile.c_str();
|
||||
size_t pathLength = strlen(path) + 1;
|
||||
aCb(reinterpret_cast<const uint8_t*>(path), pathLength, 0, aBaton);
|
||||
aCb(reinterpret_cast<const uint8_t*>(path), pathLength, mIndex, aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace gl {
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
#if defined(MOZ_X11) && !defined(MOZ_WAYLAND)
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
|
@ -13,7 +13,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
|
||||
gl_provider = 'EAGL'
|
||||
elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
|
||||
if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']:
|
||||
if CONFIG['MOZ_EGL_XRENDER_COMPOSITE'] or CONFIG['MOZ_WAYLAND']:
|
||||
gl_provider = 'EGL'
|
||||
else:
|
||||
gl_provider = 'GLX'
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIContentIterator.h"
|
||||
#include "nsIPresShellInlines.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/Event.h" // for Event::GetEventPopupControlState()
|
||||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
@ -4595,11 +4596,12 @@ nsIPresShell::RestyleForCSSRuleChanges()
|
||||
return;
|
||||
}
|
||||
|
||||
mDocument->RebuildUserFontSet();
|
||||
EnsureStyleFlush();
|
||||
mDocument->MarkUserFontSetDirty();
|
||||
|
||||
if (mPresContext) {
|
||||
mPresContext->RebuildCounterStyles();
|
||||
mPresContext->RebuildFontFeatureValues();
|
||||
mPresContext->MarkCounterStylesDirty();
|
||||
mPresContext->MarkFontFeatureValuesDirty();
|
||||
}
|
||||
|
||||
if (!mDidInitialize) {
|
||||
|
@ -314,9 +314,7 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
||||
mUsesExChUnits(false),
|
||||
mPendingViewportChange(false),
|
||||
mCounterStylesDirty(true),
|
||||
mPostedFlushCounterStyles(false),
|
||||
mFontFeatureValuesDirty(true),
|
||||
mPostedFlushFontFeatureValues(false),
|
||||
mSuppressResizeReflow(false),
|
||||
mIsVisual(false),
|
||||
mFireAfterPaintEvents(false),
|
||||
@ -2078,9 +2076,16 @@ nsPresContext::RebuildAllStyleData(nsChangeHint aExtraHint,
|
||||
MOZ_CRASH("old style system disabled");
|
||||
#endif
|
||||
}
|
||||
mDocument->RebuildUserFontSet();
|
||||
RebuildCounterStyles();
|
||||
RebuildFontFeatureValues();
|
||||
|
||||
// TODO(emilio): It's unclear to me why would these three calls below be
|
||||
// needed. In particular, RebuildAllStyleData doesn't rebuild rules or
|
||||
// specified style information and such (note the comment in
|
||||
// ServoRestyleManager::RebuildAllStyleData re. the funny semantics), so I
|
||||
// don't know why should we rebuild the user font set / counter styles /
|
||||
// etc...
|
||||
mDocument->MarkUserFontSetDirty();
|
||||
MarkCounterStylesDirty();
|
||||
MarkFontFeatureValuesDirty();
|
||||
|
||||
RestyleManager()->RebuildAllStyleData(aExtraHint, aRestyleHint);
|
||||
}
|
||||
@ -2426,27 +2431,14 @@ nsPresContext::FlushCounterStyles()
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::RebuildCounterStyles()
|
||||
nsPresContext::MarkCounterStylesDirty()
|
||||
{
|
||||
if (mCounterStyleManager->IsInitial()) {
|
||||
// Still in its initial state, no need to reset.
|
||||
// Still in its initial state, no need to touch anything.
|
||||
return;
|
||||
}
|
||||
|
||||
mCounterStylesDirty = true;
|
||||
if (mShell) {
|
||||
mShell->SetNeedStyleFlush();
|
||||
}
|
||||
if (!mPostedFlushCounterStyles) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
NewRunnableMethod("nsPresContext::HandleRebuildCounterStyles",
|
||||
this, &nsPresContext::HandleRebuildCounterStyles);
|
||||
nsresult rv =
|
||||
Document()->Dispatch(TaskCategory::Other, ev.forget());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mPostedFlushCounterStyles = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -3189,28 +3181,6 @@ nsPresContext::FlushFontFeatureValues()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::RebuildFontFeatureValues()
|
||||
{
|
||||
if (!mShell) {
|
||||
return; // we've been torn down
|
||||
}
|
||||
|
||||
mFontFeatureValuesDirty = true;
|
||||
mShell->SetNeedStyleFlush();
|
||||
|
||||
if (!mPostedFlushFontFeatureValues) {
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
NewRunnableMethod("nsPresContext::HandleRebuildFontFeatureValues",
|
||||
this, &nsPresContext::HandleRebuildFontFeatureValues);
|
||||
nsresult rv =
|
||||
Document()->Dispatch(TaskCategory::Other, ev.forget());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mPostedFlushFontFeatureValues = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRootPresContext::nsRootPresContext(nsIDocument* aDocument,
|
||||
nsPresContextType aType)
|
||||
: nsPresContext(aDocument, aType)
|
||||
|
@ -998,7 +998,7 @@ public:
|
||||
// as that value may be out of date when mPaintFlashingInitialized is false.
|
||||
bool GetPaintFlashing() const;
|
||||
|
||||
bool SuppressingResizeReflow() const { return mSuppressResizeReflow; }
|
||||
bool SuppressingResizeReflow() const { return mSuppressResizeReflow; }
|
||||
|
||||
gfxUserFontSet* GetUserFontSet(bool aFlushUserFontSet = true);
|
||||
|
||||
@ -1011,10 +1011,13 @@ public:
|
||||
void NotifyMissingFonts();
|
||||
|
||||
void FlushCounterStyles();
|
||||
void RebuildCounterStyles(); // asynchronously
|
||||
void MarkCounterStylesDirty();
|
||||
|
||||
void FlushFontFeatureValues();
|
||||
void RebuildFontFeatureValues(); // asynchronously
|
||||
void MarkFontFeatureValuesDirty()
|
||||
{
|
||||
mFontFeatureValuesDirty = true;
|
||||
}
|
||||
|
||||
// Ensure that it is safe to hand out CSS rules outside the layout
|
||||
// engine by ensuring that all CSS style sheets have unique inners
|
||||
@ -1265,16 +1268,6 @@ protected:
|
||||
|
||||
void AppUnitsPerDevPixelChanged();
|
||||
|
||||
void HandleRebuildCounterStyles() {
|
||||
mPostedFlushCounterStyles = false;
|
||||
FlushCounterStyles();
|
||||
}
|
||||
|
||||
void HandleRebuildFontFeatureValues() {
|
||||
mPostedFlushFontFeatureValues = false;
|
||||
FlushFontFeatureValues();
|
||||
}
|
||||
|
||||
bool HavePendingInputEvent();
|
||||
|
||||
// Can't be inline because we can't include nsStyleSet.h.
|
||||
@ -1478,13 +1471,9 @@ protected:
|
||||
|
||||
// Is the current mCounterStyleManager valid?
|
||||
unsigned mCounterStylesDirty : 1;
|
||||
// Do we currently have an event posted to call FlushCounterStyles?
|
||||
unsigned mPostedFlushCounterStyles: 1;
|
||||
|
||||
// Is the current mFontFeatureValuesLookup valid?
|
||||
unsigned mFontFeatureValuesDirty : 1;
|
||||
// Do we currently have an event posted to call FlushFontFeatureValues?
|
||||
unsigned mPostedFlushFontFeatureValues: 1;
|
||||
|
||||
// resize reflow is suppressed when the only change has been to zoom
|
||||
// the document rather than to change the document's dimensions
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "nsILoadContext.h"
|
||||
#include "nsINetworkPredictor.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPresShellInlines.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
@ -509,7 +510,7 @@ FontFaceSet::Add(FontFace& aFontFace, ErrorResult& aRv)
|
||||
aFontFace.Status() == FontFaceLoadStatus::Loading;
|
||||
|
||||
mNonRuleFacesDirty = true;
|
||||
RebuildUserFontSet();
|
||||
MarkUserFontSetDirty();
|
||||
mHasLoadingFontFacesIsDirty = true;
|
||||
CheckLoadingStarted();
|
||||
return this;
|
||||
@ -531,7 +532,7 @@ FontFaceSet::Clear()
|
||||
|
||||
mNonRuleFaces.Clear();
|
||||
mNonRuleFacesDirty = true;
|
||||
RebuildUserFontSet();
|
||||
MarkUserFontSetDirty();
|
||||
mHasLoadingFontFacesIsDirty = true;
|
||||
CheckLoadingFinished();
|
||||
}
|
||||
@ -560,7 +561,7 @@ FontFaceSet::Delete(FontFace& aFontFace)
|
||||
aFontFace.RemoveFontFaceSet(this);
|
||||
|
||||
mNonRuleFacesDirty = true;
|
||||
RebuildUserFontSet();
|
||||
MarkUserFontSetDirty();
|
||||
mHasLoadingFontFacesIsDirty = true;
|
||||
CheckLoadingFinished();
|
||||
return true;
|
||||
@ -1841,10 +1842,16 @@ FontFaceSet::FlushUserFontSet()
|
||||
}
|
||||
|
||||
void
|
||||
FontFaceSet::RebuildUserFontSet()
|
||||
FontFaceSet::MarkUserFontSetDirty()
|
||||
{
|
||||
if (mDocument) {
|
||||
mDocument->RebuildUserFontSet();
|
||||
// Ensure we trigger at least a style flush, that will eventually flush the
|
||||
// user font set. Otherwise the font loads that that flush may cause could
|
||||
// never be triggered.
|
||||
if (nsIPresShell* shell = mDocument->GetShell()) {
|
||||
shell->EnsureStyleFlush();
|
||||
}
|
||||
mDocument->MarkUserFontSetDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1985,7 +1992,7 @@ FontFaceSet::UserFontSet::DoRebuildUserFontSet()
|
||||
if (!mFontFaceSet) {
|
||||
return;
|
||||
}
|
||||
mFontFaceSet->RebuildUserFontSet();
|
||||
mFontFaceSet->MarkUserFontSetDirty();
|
||||
}
|
||||
|
||||
/* virtual */ already_AddRefed<gfxUserFontEntry>
|
||||
|
@ -293,7 +293,7 @@ private:
|
||||
const char* aMessage,
|
||||
uint32_t aFlags,
|
||||
nsresult aStatus);
|
||||
void RebuildUserFontSet();
|
||||
void MarkUserFontSetDirty();
|
||||
|
||||
void InsertRuleFontFace(FontFace* aFontFace, SheetType aSheetType,
|
||||
nsTArray<FontFaceRecord>& aOldRecords,
|
||||
|
@ -380,15 +380,11 @@ nsStyleUtil::AppendFontFeatureSettings(const nsTArray<gfxFontFeature>& aFeatures
|
||||
|
||||
AppendFontTagAsString(feat.mTag, aResult);
|
||||
|
||||
// output value, if necessary
|
||||
if (feat.mValue == 0) {
|
||||
// 0 ==> off
|
||||
aResult.AppendLiteral(" off");
|
||||
} else if (feat.mValue > 1) {
|
||||
// omit value if it's 1, implied by default
|
||||
if (feat.mValue != 1) {
|
||||
aResult.Append(' ');
|
||||
aResult.AppendInt(feat.mValue);
|
||||
}
|
||||
// else, omit value if 1, implied by default
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -686,6 +686,13 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"tl": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
"google", "yahoo", "bing", "amazondotcom", "ddg", "twitter"
|
||||
]
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
"default": {
|
||||
"visibleDefaultEngines": [
|
||||
|
@ -9,7 +9,7 @@
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use computed_values::{font_feature_settings, font_stretch, font_style, font_weight};
|
||||
use computed_values::{font_stretch, font_style, font_weight};
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use cssparser::{SourceLocation, CowRcStr};
|
||||
use error_reporting::{ContextualParseError, ParseErrorReporter};
|
||||
@ -25,6 +25,8 @@ use str::CssStringWriter;
|
||||
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
|
||||
use style_traits::{StyleParseErrorKind, ToCss};
|
||||
use values::computed::font::FamilyName;
|
||||
#[cfg(feature = "gecko")]
|
||||
use values::specified::font::SpecifiedFontFeatureSettings;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
/// A source for a font-face rule.
|
||||
@ -67,13 +69,17 @@ impl ToCss for UrlSource {
|
||||
/// A font-display value for a @font-face rule.
|
||||
/// The font-display descriptor determines how a font face is displayed based
|
||||
/// on whether and when it is downloaded and ready to use.
|
||||
define_css_keyword_enum!(FontDisplay:
|
||||
"auto" => Auto,
|
||||
"block" => Block,
|
||||
"swap" => Swap,
|
||||
"fallback" => Fallback,
|
||||
"optional" => Optional);
|
||||
add_impls_for_keyword_enum!(FontDisplay);
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum FontDisplay {
|
||||
Auto,
|
||||
Block,
|
||||
Swap,
|
||||
Fallback,
|
||||
Optional,
|
||||
}
|
||||
|
||||
/// A font-weight value for a @font-face rule.
|
||||
/// The font-weight CSS property specifies the weight or boldness of the font.
|
||||
@ -395,8 +401,8 @@ font_face_descriptors! {
|
||||
],
|
||||
|
||||
/// The feature settings of this font face.
|
||||
"font-feature-settings" feature_settings / mFontFeatureSettings: font_feature_settings::T = {
|
||||
font_feature_settings::T::Normal
|
||||
"font-feature-settings" feature_settings / mFontFeatureSettings: SpecifiedFontFeatureSettings = {
|
||||
font_feature_settings::SpecifiedValue::normal()
|
||||
},
|
||||
|
||||
/// The language override of this font face.
|
||||
|
@ -707,9 +707,9 @@ pub mod basic_shape {
|
||||
}
|
||||
StyleBasicShapeType::Polygon => {
|
||||
let fill_rule = if other.mFillRule == StyleFillRule::Evenodd {
|
||||
FillRule::EvenOdd
|
||||
FillRule::Evenodd
|
||||
} else {
|
||||
FillRule::NonZero
|
||||
FillRule::Nonzero
|
||||
};
|
||||
let mut coords = Vec::with_capacity(other.mCoordinates.len() / 2);
|
||||
for i in 0..(other.mCoordinates.len() / 2) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
//! Bindings for CSS Rule objects
|
||||
|
||||
use byteorder::{BigEndian, WriteBytesExt};
|
||||
use computed_values::{font_feature_settings, font_stretch, font_style, font_weight};
|
||||
use computed_values::{font_stretch, font_style, font_weight};
|
||||
use counter_style;
|
||||
use cssparser::UnicodeRange;
|
||||
use font_face::{FontFaceRuleData, Source, FontDisplay, FontWeight};
|
||||
@ -21,7 +21,7 @@ use std::fmt::{self, Write};
|
||||
use std::str;
|
||||
use str::CssStringWriter;
|
||||
use values::computed::font::FamilyName;
|
||||
use values::generics::FontSettings;
|
||||
use values::specified::font::SpecifiedFontFeatureSettings;
|
||||
|
||||
/// A @font-face rule
|
||||
pub type FontFaceRule = RefPtr<nsCSSFontFaceRule>;
|
||||
@ -50,24 +50,24 @@ impl ToNsCssValue for FontWeight {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNsCssValue for font_feature_settings::T {
|
||||
impl ToNsCssValue for SpecifiedFontFeatureSettings {
|
||||
fn convert(self, nscssvalue: &mut nsCSSValue) {
|
||||
match self {
|
||||
FontSettings::Normal => nscssvalue.set_normal(),
|
||||
FontSettings::Tag(tags) => {
|
||||
nscssvalue.set_pair_list(tags.into_iter().map(|entry| {
|
||||
let mut feature = nsCSSValue::null();
|
||||
let mut raw = [0u8; 4];
|
||||
(&mut raw[..]).write_u32::<BigEndian>(entry.tag).unwrap();
|
||||
feature.set_string(str::from_utf8(&raw).unwrap());
|
||||
|
||||
let mut index = nsCSSValue::null();
|
||||
index.set_integer(entry.value.0 as i32);
|
||||
|
||||
(feature, index)
|
||||
}))
|
||||
}
|
||||
if self.0.is_empty() {
|
||||
nscssvalue.set_normal();
|
||||
return;
|
||||
}
|
||||
|
||||
nscssvalue.set_pair_list(self.0.into_iter().map(|entry| {
|
||||
let mut feature = nsCSSValue::null();
|
||||
let mut raw = [0u8; 4];
|
||||
(&mut raw[..]).write_u32::<BigEndian>(entry.tag.0).unwrap();
|
||||
feature.set_string(str::from_utf8(&raw).unwrap());
|
||||
|
||||
let mut index = nsCSSValue::null();
|
||||
index.set_integer(entry.value.value());
|
||||
|
||||
(feature, index)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,10 +348,10 @@ impl GeckoStyleCoordConvertible for ExtremumLength {
|
||||
use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT};
|
||||
coord.set_value(CoordDataValue::Enumerated(
|
||||
match *self {
|
||||
ExtremumLength::MaxContent => NS_STYLE_WIDTH_MAX_CONTENT,
|
||||
ExtremumLength::MinContent => NS_STYLE_WIDTH_MIN_CONTENT,
|
||||
ExtremumLength::FitContent => NS_STYLE_WIDTH_FIT_CONTENT,
|
||||
ExtremumLength::FillAvailable => NS_STYLE_WIDTH_AVAILABLE,
|
||||
ExtremumLength::MozMaxContent => NS_STYLE_WIDTH_MAX_CONTENT,
|
||||
ExtremumLength::MozMinContent => NS_STYLE_WIDTH_MIN_CONTENT,
|
||||
ExtremumLength::MozFitContent => NS_STYLE_WIDTH_FIT_CONTENT,
|
||||
ExtremumLength::MozAvailable => NS_STYLE_WIDTH_AVAILABLE,
|
||||
}
|
||||
))
|
||||
}
|
||||
@ -361,12 +361,12 @@ impl GeckoStyleCoordConvertible for ExtremumLength {
|
||||
use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT};
|
||||
match coord.as_value() {
|
||||
CoordDataValue::Enumerated(NS_STYLE_WIDTH_MAX_CONTENT) =>
|
||||
Some(ExtremumLength::MaxContent),
|
||||
Some(ExtremumLength::MozMaxContent),
|
||||
CoordDataValue::Enumerated(NS_STYLE_WIDTH_MIN_CONTENT) =>
|
||||
Some(ExtremumLength::MinContent),
|
||||
Some(ExtremumLength::MozMinContent),
|
||||
CoordDataValue::Enumerated(NS_STYLE_WIDTH_FIT_CONTENT) =>
|
||||
Some(ExtremumLength::FitContent),
|
||||
CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => Some(ExtremumLength::FillAvailable),
|
||||
Some(ExtremumLength::MozFitContent),
|
||||
CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => Some(ExtremumLength::MozAvailable),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance
|
||||
|
||||
extern crate app_units;
|
||||
extern crate arrayvec;
|
||||
extern crate atomic_refcell;
|
||||
@ -72,7 +70,6 @@ extern crate smallbitvec;
|
||||
extern crate smallvec;
|
||||
#[macro_use]
|
||||
extern crate style_derive;
|
||||
#[macro_use]
|
||||
extern crate style_traits;
|
||||
extern crate time;
|
||||
extern crate uluru;
|
||||
|
@ -65,67 +65,6 @@ macro_rules! try_match_ident_ignore_ascii_case {
|
||||
}}
|
||||
}
|
||||
|
||||
macro_rules! define_numbered_css_keyword_enum {
|
||||
($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => {
|
||||
define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+);
|
||||
};
|
||||
($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => {
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
pub enum $name {
|
||||
$( $variant = $value ),+
|
||||
}
|
||||
|
||||
impl $crate::parser::Parse for $name {
|
||||
fn parse<'i, 't>(
|
||||
_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser<'i, 't>,
|
||||
) -> Result<$name, ::style_traits::ParseError<'i>> {
|
||||
try_match_ident_ignore_ascii_case! { input,
|
||||
$( $css => Ok($name::$variant), )+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::style_traits::ToCss for $name {
|
||||
fn to_css<W>(
|
||||
&self,
|
||||
dest: &mut ::style_traits::CssWriter<W>,
|
||||
) -> ::std::fmt::Result
|
||||
where
|
||||
W: ::std::fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
$( $name::$variant => dest.write_str($css) ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A macro for implementing `ToComputedValue`, and `Parse` traits for
|
||||
/// the enums defined using `define_css_keyword_enum` macro.
|
||||
///
|
||||
/// NOTE: We should either move `Parse` trait to `style_traits`
|
||||
/// or `define_css_keyword_enum` macro to this crate, but that
|
||||
/// may involve significant cleanup in both the crates.
|
||||
macro_rules! add_impls_for_keyword_enum {
|
||||
($name:ident) => {
|
||||
impl $crate::parser::Parse for $name {
|
||||
#[inline]
|
||||
fn parse<'i, 't>(
|
||||
_context: &$crate::parser::ParserContext,
|
||||
input: &mut ::cssparser::Parser<'i, 't>,
|
||||
) -> Result<Self, ::style_traits::ParseError<'i>> {
|
||||
$name::parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
trivial_to_computed_value!($name);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! define_keyword_type {
|
||||
($name: ident, $css: expr) => {
|
||||
#[allow(missing_docs)]
|
||||
|
@ -62,6 +62,7 @@ use values::computed::{NonNegativeLength, ToComputedValue, Percentage};
|
||||
use values::computed::font::{FontSize, SingleFontFamily};
|
||||
use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
use values::computed::outline::OutlineStyle;
|
||||
use values::generics::transform::TransformStyle;
|
||||
use computed_values::border_style;
|
||||
|
||||
pub mod style_structs {
|
||||
@ -1426,29 +1427,21 @@ impl Clone for ${style_struct.gecko_struct_name} {
|
||||
}
|
||||
</%def>
|
||||
|
||||
<%def name="impl_font_settings(ident, tag_type)">
|
||||
<%def name="impl_font_settings(ident, tag_type, value_type, gecko_value_type)">
|
||||
<%
|
||||
gecko_ffi_name = to_camel_case_lower(ident)
|
||||
%>
|
||||
|
||||
pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
|
||||
use values::generics::FontSettings;
|
||||
|
||||
let current_settings = &mut self.gecko.mFont.${gecko_ffi_name};
|
||||
current_settings.clear_pod();
|
||||
|
||||
match v {
|
||||
FontSettings::Normal => (), // do nothing, length is already 0
|
||||
unsafe { current_settings.set_len_pod(v.0.len() as u32) };
|
||||
|
||||
FontSettings::Tag(other_settings) => {
|
||||
unsafe { current_settings.set_len_pod(other_settings.len() as u32) };
|
||||
|
||||
for (current, other) in current_settings.iter_mut().zip(other_settings) {
|
||||
current.mTag = other.tag;
|
||||
current.mValue = other.value.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
for (current, other) in current_settings.iter_mut().zip(v.0.iter()) {
|
||||
current.mTag = other.tag.0;
|
||||
current.mValue = other.value as ${gecko_value_type};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn copy_${ident}_from(&mut self, other: &Self) {
|
||||
@ -1470,20 +1463,17 @@ impl Clone for ${style_struct.gecko_struct_name} {
|
||||
}
|
||||
|
||||
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
|
||||
use values::generics::{FontSettings, FontSettingTag, ${tag_type}} ;
|
||||
use values::generics::font::{FontSettings, ${tag_type}};
|
||||
use values::specified::font::FontTag;
|
||||
|
||||
if self.gecko.mFont.${gecko_ffi_name}.len() == 0 {
|
||||
FontSettings::Normal
|
||||
} else {
|
||||
FontSettings::Tag(
|
||||
self.gecko.mFont.${gecko_ffi_name}.iter().map(|gecko_font_setting| {
|
||||
FontSettingTag {
|
||||
tag: gecko_font_setting.mTag,
|
||||
value: ${tag_type}(gecko_font_setting.mValue),
|
||||
}
|
||||
}).collect()
|
||||
)
|
||||
}
|
||||
FontSettings(
|
||||
self.gecko.mFont.${gecko_ffi_name}.iter().map(|gecko_font_setting| {
|
||||
${tag_type} {
|
||||
tag: FontTag(gecko_font_setting.mTag),
|
||||
value: gecko_font_setting.mValue as ${value_type},
|
||||
}
|
||||
}).collect::<Vec<_>>().into_boxed_slice()
|
||||
)
|
||||
}
|
||||
</%def>
|
||||
|
||||
@ -2337,8 +2327,10 @@ fn static_assert() {
|
||||
<%self:impl_trait style_struct_name="Font"
|
||||
skip_longhands="${skip_font_longhands}">
|
||||
|
||||
<% impl_font_settings("font_feature_settings", "FontSettingTagInt") %>
|
||||
<% impl_font_settings("font_variation_settings", "FontSettingTagFloat") %>
|
||||
// Negative numbers are invalid at parse time, but <integer> is still an
|
||||
// i32.
|
||||
<% impl_font_settings("font_feature_settings", "FeatureTagValue", "i32", "u32") %>
|
||||
<% impl_font_settings("font_variation_settings", "VariationValue", "f32", "f32") %>
|
||||
|
||||
pub fn fixup_none_generic(&mut self, device: &Device) {
|
||||
self.gecko.mFont.systemFont = false;
|
||||
@ -3345,6 +3337,25 @@ fn static_assert() {
|
||||
self.copy_transition_property_from(other)
|
||||
}
|
||||
|
||||
// Hand-written because the Mako helpers transform `Preserve3d` into `PRESERVE3D`.
|
||||
pub fn set_transform_style(&mut self, v: TransformStyle) {
|
||||
self.gecko.mTransformStyle = match v {
|
||||
TransformStyle::Flat => structs::NS_STYLE_TRANSFORM_STYLE_FLAT as u8,
|
||||
TransformStyle::Preserve3d => structs::NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D as u8,
|
||||
};
|
||||
}
|
||||
|
||||
// Hand-written because the Mako helpers transform `Preserve3d` into `PRESERVE3D`.
|
||||
pub fn clone_transform_style(&self) -> TransformStyle {
|
||||
match self.gecko.mTransformStyle as u32 {
|
||||
structs::NS_STYLE_TRANSFORM_STYLE_FLAT => TransformStyle::Flat,
|
||||
structs::NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D => TransformStyle::Preserve3d,
|
||||
_ => panic!("illegal transform style"),
|
||||
}
|
||||
}
|
||||
|
||||
${impl_simple_copy('transform_style', 'mTransformStyle')}
|
||||
|
||||
${impl_transition_count('property', 'Property')}
|
||||
|
||||
pub fn animations_equals(&self, other: &Self) -> bool {
|
||||
@ -5081,7 +5092,7 @@ fn static_assert() {
|
||||
coord.0.to_gecko_style_coord(&mut shape.mCoordinates[2 * i]);
|
||||
coord.1.to_gecko_style_coord(&mut shape.mCoordinates[2 * i + 1]);
|
||||
}
|
||||
shape.mFillRule = if poly.fill == FillRule::EvenOdd {
|
||||
shape.mFillRule = if poly.fill == FillRule::Evenodd {
|
||||
StyleFillRule::Evenodd
|
||||
} else {
|
||||
StyleFillRule::Nonzero
|
||||
|
@ -424,20 +424,13 @@
|
||||
use properties::longhands::system_font::SystemFont;
|
||||
|
||||
pub mod computed_value {
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
|
||||
use style_traits::ParseError;
|
||||
define_css_keyword_enum! { T:
|
||||
% for value in keyword.values_for(product):
|
||||
"${value}" => ${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
|
||||
impl Parse for T {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
T::parse(input)
|
||||
}
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse)]
|
||||
#[derive(PartialEq, ToCss)]
|
||||
pub enum T {
|
||||
% for value in keyword.values_for(product):
|
||||
${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
|
||||
${gecko_keyword_conversion(keyword, keyword.values_for(product), type="T", cast_to="i32")}
|
||||
@ -604,26 +597,32 @@
|
||||
|
||||
<%def name="inner_body(keyword, extra_specified=None, needs_conversion=False)">
|
||||
% if extra_specified or keyword.aliases_for(product):
|
||||
define_css_keyword_enum! { SpecifiedValue:
|
||||
values {
|
||||
% for value in keyword.values_for(product) + (extra_specified or "").split():
|
||||
"${value}" => ${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
aliases {
|
||||
% for alias, value in keyword.aliases_for(product).iteritems():
|
||||
"${alias}" => ${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum SpecifiedValue {
|
||||
% for value in keyword.values_for(product) + (extra_specified or "").split():
|
||||
<%
|
||||
aliases = []
|
||||
for alias, v in keyword.aliases_for(product).iteritems():
|
||||
if value == v:
|
||||
aliases.append(alias)
|
||||
%>
|
||||
% if aliases:
|
||||
#[css(aliases = "${','.join(aliases)}")]
|
||||
% endif
|
||||
${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
% else:
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
% endif
|
||||
pub mod computed_value {
|
||||
define_css_keyword_enum! { T:
|
||||
% for value in data.longhands_by_name[name].keyword.values_for(product):
|
||||
"${value}" => ${to_camel_case(value)},
|
||||
% endfor
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum T {
|
||||
% for value in data.longhands_by_name[name].keyword.values_for(product):
|
||||
${to_camel_case(value)},
|
||||
% endfor
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
@ -639,13 +638,6 @@
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(input)
|
||||
}
|
||||
impl Parse for SpecifiedValue {
|
||||
#[inline]
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
SpecifiedValue::parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
% if needs_conversion:
|
||||
<%
|
||||
|
@ -17,8 +17,6 @@ use properties::{CSSWideKeyword, PropertyDeclaration};
|
||||
use properties::longhands;
|
||||
use properties::longhands::font_weight::computed_value::T as FontWeight;
|
||||
use properties::longhands::font_stretch::computed_value::T as FontStretch;
|
||||
#[cfg(feature = "gecko")]
|
||||
use properties::longhands::font_variation_settings::computed_value::T as FontVariationSettings;
|
||||
use properties::longhands::visibility::computed_value::T as Visibility;
|
||||
#[cfg(feature = "gecko")]
|
||||
use properties::PropertyId;
|
||||
@ -51,14 +49,15 @@ use values::computed::transform::Translate as ComputedTranslate;
|
||||
use values::computed::transform::Scale as ComputedScale;
|
||||
use values::generics::transform::{self, Rotate, Translate, Scale, Transform, TransformOperation};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
#[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings;
|
||||
#[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag;
|
||||
#[cfg(feature = "gecko")] use values::generics::FontSettingTagFloat;
|
||||
use values::generics::font::FontSettings as GenericFontSettings;
|
||||
use values::computed::font::FontVariationSettings;
|
||||
use values::generics::font::VariationValue;
|
||||
use values::generics::NonNegative;
|
||||
use values::generics::effects::Filter;
|
||||
use values::generics::position as generic_position;
|
||||
use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint};
|
||||
use values::generics::svg::{SVGPaintKind, SVGStrokeDashArray, SVGOpacity};
|
||||
use values::specified::font::FontTag;
|
||||
|
||||
/// <https://drafts.csswg.org/css-transitions/#animtype-repeatable-list>
|
||||
pub trait RepeatableListAnimatable: Animate {}
|
||||
@ -816,18 +815,16 @@ impl Into<FontStretch> for f64 {
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def>
|
||||
#[cfg(feature = "gecko")]
|
||||
impl Animate for FontVariationSettings {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
FontSettingTagIter::new(self, other)?
|
||||
.map(|r| r.and_then(|(st, ot)| st.animate(&ot, procedure)))
|
||||
.collect::<Result<Vec<FontSettingTag>, ()>>()
|
||||
.map(GenericFontSettings::Tag)
|
||||
.collect::<Result<Vec<ComputedVariationValue>, ()>>()
|
||||
.map(|v| GenericFontSettings(v.into_boxed_slice()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ComputeSquaredDistance for FontVariationSettings {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
@ -837,7 +834,6 @@ impl ComputeSquaredDistance for FontVariationSettings {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ToAnimatedZero for FontVariationSettings {
|
||||
#[inline]
|
||||
fn to_animated_zero(&self) -> Result<Self, ()> {
|
||||
@ -845,49 +841,21 @@ impl ToAnimatedZero for FontVariationSettings {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl Animate for FontSettingTag {
|
||||
#[inline]
|
||||
fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
|
||||
if self.tag != other.tag {
|
||||
return Err(());
|
||||
}
|
||||
let value = self.value.animate(&other.value, procedure)?;
|
||||
Ok(FontSettingTag {
|
||||
tag: self.tag,
|
||||
value,
|
||||
})
|
||||
}
|
||||
}
|
||||
type ComputedVariationValue = VariationValue<Number>;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl ComputeSquaredDistance for FontSettingTag {
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
if self.tag != other.tag {
|
||||
return Err(());
|
||||
}
|
||||
self.value.compute_squared_distance(&other.value)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
type FontSettingTag = GenericFontSettingTag<FontSettingTagFloat>;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
// FIXME: Could do a rename, this is only used for font variations.
|
||||
struct FontSettingTagIterState<'a> {
|
||||
tags: Vec<(&'a FontSettingTag)>,
|
||||
tags: Vec<(&'a ComputedVariationValue)>,
|
||||
index: usize,
|
||||
prev_tag: u32,
|
||||
prev_tag: FontTag,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<'a> FontSettingTagIterState<'a> {
|
||||
fn new(tags: Vec<(&'a FontSettingTag)>) -> FontSettingTagIterState<'a> {
|
||||
fn new(tags: Vec<<&'a ComputedVariationValue>) -> FontSettingTagIterState<'a> {
|
||||
FontSettingTagIterState {
|
||||
index: tags.len(),
|
||||
tags,
|
||||
prev_tag: 0,
|
||||
prev_tag: FontTag(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -897,12 +865,13 @@ impl<'a> FontSettingTagIterState<'a> {
|
||||
/// [CSS fonts level 4](https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-variation-settings)
|
||||
/// defines the animation of font-variation-settings as follows:
|
||||
///
|
||||
/// Two declarations of font-feature-settings[sic] can be animated between if they are "like".
|
||||
/// "Like" declarations are ones where the same set of properties appear (in any order).
|
||||
/// Because succesive[sic] duplicate properties are applied instead of prior duplicate
|
||||
/// properties, two declarations can be "like" even if they have differing number of
|
||||
/// properties. If two declarations are "like" then animation occurs pairwise between
|
||||
/// corresponding values in the declarations.
|
||||
/// Two declarations of font-feature-settings[sic] can be animated between if
|
||||
/// they are "like". "Like" declarations are ones where the same set of
|
||||
/// properties appear (in any order). Because succesive[sic] duplicate
|
||||
/// properties are applied instead of prior duplicate properties, two
|
||||
/// declarations can be "like" even if they have differing number of
|
||||
/// properties. If two declarations are "like" then animation occurs pairwise
|
||||
/// between corresponding values in the declarations.
|
||||
///
|
||||
/// In other words if we have the following lists:
|
||||
///
|
||||
@ -914,9 +883,10 @@ impl<'a> FontSettingTagIterState<'a> {
|
||||
/// "wdth" 5, "wght" 2
|
||||
/// "wght" 4, "wdth" 10
|
||||
///
|
||||
/// This iterator supports this by sorting the two lists, then iterating them in reverse,
|
||||
/// and skipping entries with repeated tag names. It will return Some(Err()) if it reaches the
|
||||
/// end of one list before the other, or if the tag names do not match.
|
||||
/// This iterator supports this by sorting the two lists, then iterating them in
|
||||
/// reverse, and skipping entries with repeated tag names. It will return
|
||||
/// Some(Err()) if it reaches the end of one list before the other, or if the
|
||||
/// tag names do not match.
|
||||
///
|
||||
/// For the above example, this iterator would return:
|
||||
///
|
||||
@ -924,37 +894,33 @@ impl<'a> FontSettingTagIterState<'a> {
|
||||
/// Some(Ok("wdth" 5, "wdth" 10))
|
||||
/// None
|
||||
///
|
||||
#[cfg(feature = "gecko")]
|
||||
struct FontSettingTagIter<'a> {
|
||||
a_state: FontSettingTagIterState<'a>,
|
||||
b_state: FontSettingTagIterState<'a>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<'a> FontSettingTagIter<'a> {
|
||||
fn new(
|
||||
a_settings: &'a FontVariationSettings,
|
||||
b_settings: &'a FontVariationSettings,
|
||||
) -> Result<FontSettingTagIter<'a>, ()> {
|
||||
if let (&GenericFontSettings::Tag(ref a_tags), &GenericFontSettings::Tag(ref b_tags)) = (a_settings, b_settings)
|
||||
{
|
||||
fn as_new_sorted_tags(tags: &Vec<FontSettingTag>) -> Vec<(&FontSettingTag)> {
|
||||
use std::iter::FromIterator;
|
||||
let mut sorted_tags: Vec<(&FontSettingTag)> = Vec::from_iter(tags.iter());
|
||||
sorted_tags.sort_by_key(|k| k.tag);
|
||||
sorted_tags
|
||||
};
|
||||
|
||||
Ok(FontSettingTagIter {
|
||||
a_state: FontSettingTagIterState::new(as_new_sorted_tags(a_tags)),
|
||||
b_state: FontSettingTagIterState::new(as_new_sorted_tags(b_tags)),
|
||||
})
|
||||
} else {
|
||||
Err(())
|
||||
if a_settings.0.is_empty() || b_settings.0.is_empty() {
|
||||
return Err(());
|
||||
}
|
||||
fn as_new_sorted_tags(tags: &[ComputedVariationValue]) -> Vec<<&ComputedVariationValue> {
|
||||
use std::iter::FromIterator;
|
||||
let mut sorted_tags = Vec::from_iter(tags.iter());
|
||||
sorted_tags.sort_by_key(|k| k.tag.0);
|
||||
sorted_tags
|
||||
};
|
||||
|
||||
Ok(FontSettingTagIter {
|
||||
a_state: FontSettingTagIterState::new(as_new_sorted_tags(&a_settings.0)),
|
||||
b_state: FontSettingTagIterState::new(as_new_sorted_tags(&b_settings.0)),
|
||||
})
|
||||
}
|
||||
|
||||
fn next_tag(state: &mut FontSettingTagIterState<'a>) -> Option<(&'a FontSettingTag)> {
|
||||
fn next_tag(state: &mut FontSettingTagIterState<'a>) -> Option<<&'a ComputedVariationValue> {
|
||||
if state.index == 0 {
|
||||
return None;
|
||||
}
|
||||
@ -970,11 +936,10 @@ impl<'a> FontSettingTagIter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<'a> Iterator for FontSettingTagIter<'a> {
|
||||
type Item = Result<(&'a FontSettingTag, &'a FontSettingTag), ()>;
|
||||
type Item = Result<(&'a ComputedVariationValue, &'a ComputedVariationValue), ()>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<(&'a FontSettingTag, &'a FontSettingTag), ()>> {
|
||||
fn next(&mut self) -> Option<Result<(&'a ComputedVariationValue, &'a ComputedVariationValue), ()>> {
|
||||
match (
|
||||
FontSettingTagIter::next_tag(&mut self.a_state),
|
||||
FontSettingTagIter::next_tag(&mut self.b_state),
|
||||
|
@ -32,13 +32,16 @@
|
||||
ignored_when_colors_disabled=True,
|
||||
)}
|
||||
|
||||
${helpers.predefined_type("border-%s-style" % side_name, "BorderStyle",
|
||||
"specified::BorderStyle::None",
|
||||
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
|
||||
spec=maybe_logical_spec(side, "style"),
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
animation_value_type="discrete" if not is_logical else "none",
|
||||
logical=is_logical)}
|
||||
${helpers.predefined_type(
|
||||
"border-%s-style" % side_name, "BorderStyle",
|
||||
"specified::BorderStyle::None",
|
||||
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
|
||||
spec=maybe_logical_spec(side, "style"),
|
||||
flags="APPLIES_TO_FIRST_LETTER",
|
||||
animation_value_type="discrete" if not is_logical else "none",
|
||||
logical=is_logical,
|
||||
needs_context=False,
|
||||
)}
|
||||
|
||||
${helpers.predefined_type("border-%s-width" % side_name,
|
||||
"BorderSideWidth",
|
||||
@ -112,11 +115,14 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect",
|
||||
pub struct SpecifiedValue(pub RepeatKeyword,
|
||||
pub Option<RepeatKeyword>);
|
||||
|
||||
define_css_keyword_enum!(RepeatKeyword:
|
||||
"stretch" => Stretch,
|
||||
"repeat" => Repeat,
|
||||
"round" => Round,
|
||||
"space" => Space);
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum RepeatKeyword {
|
||||
Stretch,
|
||||
Repeat,
|
||||
Round,
|
||||
Space,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
|
@ -526,14 +526,16 @@ ${helpers.single_keyword("transform-box",
|
||||
gecko_inexhaustive="True",
|
||||
animation_value_type="discrete")}
|
||||
|
||||
// `auto` keyword is not supported in gecko yet.
|
||||
${helpers.single_keyword("transform-style",
|
||||
"auto flat preserve-3d" if product == "servo" else
|
||||
"flat preserve-3d",
|
||||
spec="https://drafts.csswg.org/css-transforms/#transform-style-property",
|
||||
extra_prefixes="moz webkit",
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
animation_value_type="discrete")}
|
||||
${helpers.predefined_type(
|
||||
"transform-style",
|
||||
"TransformStyle",
|
||||
"computed::TransformStyle::" + ("Auto" if product == "servo" else "Flat"),
|
||||
spec="https://drafts.csswg.org/css-transforms-2/#transform-style-property",
|
||||
needs_context=False,
|
||||
extra_prefixes="moz webkit",
|
||||
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
|
||||
animation_value_type="discrete",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type("transform-origin",
|
||||
"TransformOrigin",
|
||||
|
@ -144,7 +144,6 @@ ${helpers.predefined_type("font-feature-settings",
|
||||
initial_value="computed::FontFeatureSettings::normal()",
|
||||
initial_specified_value="specified::FontFeatureSettings::normal()",
|
||||
extra_prefixes="moz",
|
||||
boxed=True,
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings")}
|
||||
@ -157,10 +156,10 @@ https://drafts.csswg.org/css-fonts-4/#low-level-font-variation-settings-control-
|
||||
%>
|
||||
|
||||
${helpers.predefined_type("font-variation-settings",
|
||||
"FontVariantSettings",
|
||||
"FontVariationSettings",
|
||||
products="gecko",
|
||||
gecko_pref="layout.css.font-variations.enabled",
|
||||
initial_value="specified::FontVariantSettings::normal()",
|
||||
initial_value="computed::FontVariationSettings::normal()",
|
||||
animation_value_type="ComputedValue",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="${variation_spec}")}
|
||||
|
@ -279,12 +279,14 @@ ${helpers.predefined_type(
|
||||
}
|
||||
}
|
||||
|
||||
define_css_keyword_enum!(ShapeKeyword:
|
||||
"dot" => Dot,
|
||||
"circle" => Circle,
|
||||
"double-circle" => DoubleCircle,
|
||||
"triangle" => Triangle,
|
||||
"sesame" => Sesame);
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum ShapeKeyword {
|
||||
Dot,
|
||||
Circle,
|
||||
DoubleCircle,
|
||||
Triangle,
|
||||
Sesame,
|
||||
}
|
||||
|
||||
impl ShapeKeyword {
|
||||
pub fn char(&self, fill: bool) -> &str {
|
||||
@ -381,14 +383,19 @@ ${helpers.predefined_type(
|
||||
|
||||
<%helpers:longhand name="text-emphasis-position" animation_value_type="discrete" products="gecko"
|
||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-position">
|
||||
define_css_keyword_enum!(HorizontalWritingModeValue:
|
||||
"over" => Over,
|
||||
"under" => Under);
|
||||
add_impls_for_keyword_enum!(VerticalWritingModeValue);
|
||||
define_css_keyword_enum!(VerticalWritingModeValue:
|
||||
"right" => Right,
|
||||
"left" => Left);
|
||||
add_impls_for_keyword_enum!(HorizontalWritingModeValue);
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum HorizontalWritingModeValue {
|
||||
Over,
|
||||
Under,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum VerticalWritingModeValue {
|
||||
Right,
|
||||
Left,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||
pub struct SpecifiedValue(pub HorizontalWritingModeValue, pub VerticalWritingModeValue);
|
||||
|
@ -9,9 +9,13 @@ ${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Co
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-color",
|
||||
allow_quirks=True)}
|
||||
|
||||
${helpers.four_sides_shorthand("border-style", "border-%s-style",
|
||||
"specified::BorderStyle::parse",
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-style")}
|
||||
${helpers.four_sides_shorthand(
|
||||
"border-style",
|
||||
"border-%s-style",
|
||||
"specified::BorderStyle::parse",
|
||||
needs_context=False,
|
||||
spec="https://drafts.csswg.org/css-backgrounds/#border-style",
|
||||
)}
|
||||
|
||||
<%helpers:shorthand name="border-width" sub_properties="${
|
||||
' '.join('border-%s-width' % side
|
||||
@ -63,7 +67,7 @@ pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
}
|
||||
}
|
||||
if style.is_none() {
|
||||
if let Ok(value) = input.try(|i| BorderStyle::parse(context, i)) {
|
||||
if let Ok(value) = input.try(BorderStyle::parse) {
|
||||
style = Some(value);
|
||||
any = true;
|
||||
continue
|
||||
|
@ -22,13 +22,13 @@ use std::slice;
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
use values::CSSFloat;
|
||||
use values::animated::{ToAnimatedValue, ToAnimatedZero};
|
||||
use values::computed::{Context, NonNegativeLength, ToComputedValue};
|
||||
use values::generics::{FontSettings, FontSettingTagInt};
|
||||
use values::computed::{Context, NonNegativeLength, ToComputedValue, Integer, Number};
|
||||
use values::generics::font::{FontSettings, FeatureTagValue, VariationValue};
|
||||
use values::specified::font as specified;
|
||||
use values::specified::length::{FontBaseSize, NoCalcLength};
|
||||
|
||||
pub use values::computed::Length as MozScriptMinSize;
|
||||
pub use values::specified::font::{XTextZoom, XLang, MozScriptSizeMultiplier, FontSynthesis, FontVariantSettings};
|
||||
pub use values::specified::font::{XTextZoom, XLang, MozScriptSizeMultiplier, FontSynthesis};
|
||||
|
||||
/// As of CSS Fonts Module Level 3, only the following values are
|
||||
/// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||
@ -712,8 +712,11 @@ pub type FontVariantLigatures = specified::VariantLigatures;
|
||||
/// Use VariantNumeric as computed type of FontVariantNumeric
|
||||
pub type FontVariantNumeric = specified::VariantNumeric;
|
||||
|
||||
/// Use FontSettings as computed type of FontFeatureSettings
|
||||
pub type FontFeatureSettings = FontSettings<FontSettingTagInt>;
|
||||
/// Use FontSettings as computed type of FontFeatureSettings.
|
||||
pub type FontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
|
||||
|
||||
/// The computed value for font-variation-settings.
|
||||
pub type FontVariationSettings = FontSettings<VariationValue<Number>>;
|
||||
|
||||
/// font-language-override can only have a single three-letter
|
||||
/// OpenType "language system" tag, so we should be able to compute
|
||||
|
@ -40,7 +40,7 @@ pub use self::background::{BackgroundSize, BackgroundRepeat};
|
||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||
pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||
pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
|
||||
pub use self::font::{FontFamily, FontLanguageOverride, FontVariationSettings, FontVariantEastAsian};
|
||||
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
|
||||
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
|
||||
pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior, Contain};
|
||||
@ -73,7 +73,8 @@ pub use self::svg::MozContextProperties;
|
||||
pub use self::table::XSpan;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing};
|
||||
pub use self::time::Time;
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate, Scale};
|
||||
pub use self::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation};
|
||||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
pub use self::ui::MozForceBrokenImageIcon;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -18,6 +18,8 @@ use values::generics::transform::TimingFunction as GenericTimingFunction;
|
||||
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
|
||||
use values::generics::transform::Translate as GenericTranslate;
|
||||
|
||||
pub use values::generics::transform::TransformStyle;
|
||||
|
||||
/// A single operation in a computed CSS `transform`
|
||||
pub type TransformOperation = GenericTransformOperation<
|
||||
Angle,
|
||||
|
@ -30,13 +30,16 @@ pub enum GeometryBox {
|
||||
pub type FloatAreaShape<BasicShape, Image> = ShapeSource<BasicShape, ShapeBox, Image>;
|
||||
|
||||
// https://drafts.csswg.org/css-shapes-1/#typedef-shape-box
|
||||
define_css_keyword_enum!(ShapeBox:
|
||||
"margin-box" => MarginBox,
|
||||
"border-box" => BorderBox,
|
||||
"padding-box" => PaddingBox,
|
||||
"content-box" => ContentBox
|
||||
);
|
||||
add_impls_for_keyword_enum!(ShapeBox);
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum ShapeBox {
|
||||
MarginBox,
|
||||
BorderBox,
|
||||
PaddingBox,
|
||||
ContentBox,
|
||||
}
|
||||
|
||||
/// A shape source, for some reference box.
|
||||
#[allow(missing_docs)]
|
||||
@ -117,11 +120,14 @@ pub struct Polygon<LengthOrPercentage> {
|
||||
// NOTE: Basic shapes spec says that these are the only two values, however
|
||||
// https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
|
||||
// says that it can also be `inherit`
|
||||
define_css_keyword_enum!(FillRule:
|
||||
"nonzero" => NonZero,
|
||||
"evenodd" => EvenOdd
|
||||
);
|
||||
add_impls_for_keyword_enum!(FillRule);
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum FillRule {
|
||||
Nonzero,
|
||||
Evenodd,
|
||||
}
|
||||
|
||||
// FIXME(nox): Implement ComputeSquaredDistance for T types and stop
|
||||
// using PartialEq here, this will let us derive this impl.
|
||||
@ -239,5 +245,5 @@ impl<L: ToCss> ToCss for Polygon<L> {
|
||||
|
||||
impl Default for FillRule {
|
||||
#[inline]
|
||||
fn default() -> Self { FillRule::NonZero }
|
||||
fn default() -> Self { FillRule::Nonzero }
|
||||
}
|
||||
|
119
servo/components/style/values/generics/font.rs
Normal file
119
servo/components/style/values/generics/font.rs
Normal file
@ -0,0 +1,119 @@
|
||||
/* 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/. */
|
||||
|
||||
//! Generic types for font stuff.
|
||||
|
||||
use cssparser::Parser;
|
||||
use num_traits::One;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ParseError, ToCss};
|
||||
use values::distance::{ComputeSquaredDistance, SquaredDistance};
|
||||
use values::specified::font::FontTag;
|
||||
|
||||
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FeatureTagValue<Integer> {
|
||||
/// A four-character tag, packed into a u32 (one byte per character).
|
||||
pub tag: FontTag,
|
||||
/// The actual value.
|
||||
pub value: Integer,
|
||||
}
|
||||
|
||||
impl<Integer> ToCss for FeatureTagValue<Integer>
|
||||
where
|
||||
Integer: One + ToCss + PartialEq,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
self.tag.to_css(dest)?;
|
||||
// Don't serialize the default value.
|
||||
if self.value != Integer::one() {
|
||||
dest.write_char(' ')?;
|
||||
self.value.to_css(dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Variation setting for a single feature, see:
|
||||
///
|
||||
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
|
||||
#[derive(Animate, Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||
pub struct VariationValue<Number> {
|
||||
/// A four-character tag, packed into a u32 (one byte per character).
|
||||
#[animation(constant)]
|
||||
pub tag: FontTag,
|
||||
/// The actual value.
|
||||
pub value: Number,
|
||||
}
|
||||
|
||||
impl<Number> ComputeSquaredDistance for VariationValue<Number>
|
||||
where
|
||||
Number: ComputeSquaredDistance,
|
||||
{
|
||||
#[inline]
|
||||
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
|
||||
if self.tag != other.tag {
|
||||
return Err(());
|
||||
}
|
||||
self.value.compute_squared_distance(&other.value)
|
||||
}
|
||||
}
|
||||
|
||||
/// A value both for font-variation-settings and font-feature-settings.
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FontSettings<T>(pub Box<[T]>);
|
||||
|
||||
impl<T> FontSettings<T> {
|
||||
/// Default value of font settings as `normal`.
|
||||
#[inline]
|
||||
pub fn normal() -> Self {
|
||||
FontSettings(vec![].into_boxed_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for FontSettings<T> {
|
||||
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings
|
||||
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(Self::normal());
|
||||
}
|
||||
|
||||
Ok(FontSettings(
|
||||
input.parse_comma_separated(|i| T::parse(context, i))?.into_boxed_slice()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ToCss> ToCss for FontSettings<T> {
|
||||
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings
|
||||
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("normal");
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
for item in self.0.iter() {
|
||||
if !first {
|
||||
dest.write_str(", ")?;
|
||||
}
|
||||
first = false;
|
||||
item.to_css(dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -140,12 +140,15 @@ impl Parse for GridLine<specified::Integer> {
|
||||
}
|
||||
}
|
||||
|
||||
define_css_keyword_enum!{ TrackKeyword:
|
||||
"auto" => Auto,
|
||||
"max-content" => MaxContent,
|
||||
"min-content" => MinContent
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum TrackKeyword {
|
||||
Auto,
|
||||
MaxContent,
|
||||
MinContent,
|
||||
}
|
||||
add_impls_for_keyword_enum!(TrackKeyword);
|
||||
|
||||
/// A track breadth for explicit grid track sizing. It's generic solely to
|
||||
/// avoid re-implementing it for the computed type.
|
||||
|
@ -97,15 +97,18 @@ pub enum Ellipse<LengthOrPercentage> {
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css-images/#typedef-extent-keyword>
|
||||
define_css_keyword_enum!(ShapeExtent:
|
||||
"closest-side" => ClosestSide,
|
||||
"farthest-side" => FarthestSide,
|
||||
"closest-corner" => ClosestCorner,
|
||||
"farthest-corner" => FarthestCorner,
|
||||
"contain" => Contain,
|
||||
"cover" => Cover
|
||||
);
|
||||
add_impls_for_keyword_enum!(ShapeExtent);
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum ShapeExtent {
|
||||
ClosestSide,
|
||||
FarthestSide,
|
||||
ClosestCorner,
|
||||
FarthestCorner,
|
||||
Contain,
|
||||
Cover,
|
||||
}
|
||||
|
||||
/// A gradient item.
|
||||
/// <https://drafts.csswg.org/css-images-4/#color-stop-syntax>
|
||||
|
@ -8,9 +8,7 @@
|
||||
use counter_style::{Symbols, parse_counter_style_name};
|
||||
use cssparser::Parser;
|
||||
use parser::{Parse, ParserContext};
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
|
||||
use style_traits::{StyleParseErrorKind, ToCss};
|
||||
use style_traits::{ParseError, StyleParseErrorKind};
|
||||
use super::CustomIdent;
|
||||
|
||||
pub mod background;
|
||||
@ -20,6 +18,7 @@ pub mod border;
|
||||
pub mod box_;
|
||||
pub mod effects;
|
||||
pub mod flex;
|
||||
pub mod font;
|
||||
#[cfg(feature = "gecko")]
|
||||
pub mod gecko;
|
||||
pub mod grid;
|
||||
@ -32,14 +31,17 @@ pub mod text;
|
||||
pub mod transform;
|
||||
|
||||
// https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type
|
||||
define_css_keyword_enum! { SymbolsType:
|
||||
"cyclic" => Cyclic,
|
||||
"numeric" => Numeric,
|
||||
"alphabetic" => Alphabetic,
|
||||
"symbolic" => Symbolic,
|
||||
"fixed" => Fixed,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum SymbolsType {
|
||||
Cyclic,
|
||||
Numeric,
|
||||
Alphabetic,
|
||||
Symbolic,
|
||||
Fixed,
|
||||
}
|
||||
add_impls_for_keyword_enum!(SymbolsType);
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl SymbolsType {
|
||||
@ -128,167 +130,6 @@ impl Parse for CounterStyleOrNone {
|
||||
}
|
||||
}
|
||||
|
||||
/// A settings tag, defined by a four-character tag and a setting value
|
||||
///
|
||||
/// For font-feature-settings, this is a tag and an integer,
|
||||
/// for font-variation-settings this is a tag and a float
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FontSettingTag<T> {
|
||||
/// A four-character tag, packed into a u32 (one byte per character)
|
||||
pub tag: u32,
|
||||
/// The value
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<T> OneOrMoreSeparated for FontSettingTag<T> {
|
||||
type S = Comma;
|
||||
}
|
||||
|
||||
impl<T: ToCss> ToCss for FontSettingTag<T> {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use std::str;
|
||||
|
||||
let mut raw = [0u8; 4];
|
||||
BigEndian::write_u32(&mut raw, self.tag);
|
||||
str::from_utf8(&raw).unwrap_or_default().to_css(dest)?;
|
||||
|
||||
self.value.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for FontSettingTag<T> {
|
||||
/// <https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings>
|
||||
/// <https://drafts.csswg.org/css-fonts-4/#low-level-font-variation->
|
||||
/// settings-control-the-font-variation-settings-property
|
||||
/// <string> [ on | off | <integer> ]
|
||||
/// <string> <number>
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
use byteorder::{ReadBytesExt, BigEndian};
|
||||
use std::io::Cursor;
|
||||
|
||||
let u_tag;
|
||||
{
|
||||
let location = input.current_source_location();
|
||||
let tag = input.expect_string()?;
|
||||
|
||||
// allowed strings of length 4 containing chars: <U+20, U+7E>
|
||||
if tag.len() != 4 ||
|
||||
tag.chars().any(|c| c < ' ' || c > '~')
|
||||
{
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
||||
let mut raw = Cursor::new(tag.as_bytes());
|
||||
u_tag = raw.read_u32::<BigEndian>().unwrap();
|
||||
}
|
||||
|
||||
Ok(FontSettingTag { tag: u_tag, value: T::parse(context, input)? })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A font settings value for font-variation-settings or font-feature-settings
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||
pub enum FontSettings<T> {
|
||||
/// No settings (default)
|
||||
Normal,
|
||||
/// Set of settings
|
||||
Tag(Vec<FontSettingTag<T>>)
|
||||
}
|
||||
|
||||
impl <T> FontSettings<T> {
|
||||
#[inline]
|
||||
/// Default value of font settings as `normal`
|
||||
pub fn normal() -> Self {
|
||||
FontSettings::Normal
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for FontSettings<T> {
|
||||
/// <https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings>
|
||||
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(FontSettings::Normal);
|
||||
}
|
||||
Vec::parse(context, input).map(FontSettings::Tag)
|
||||
}
|
||||
}
|
||||
|
||||
/// An integer that can also parse "on" and "off",
|
||||
/// for font-feature-settings
|
||||
///
|
||||
/// Do not use this type anywhere except within FontSettings
|
||||
/// because it serializes with the preceding space
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FontSettingTagInt(pub u32);
|
||||
|
||||
/// A number value to be used for font-variation-settings
|
||||
///
|
||||
/// Do not use this type anywhere except within FontSettings
|
||||
/// because it serializes with the preceding space
|
||||
#[cfg_attr(feature = "gecko", derive(Animate, ComputeSquaredDistance))]
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FontSettingTagFloat(pub f32);
|
||||
|
||||
impl ToCss for FontSettingTagInt {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
match self.0 {
|
||||
1 => Ok(()),
|
||||
0 => dest.write_str(" off"),
|
||||
x => {
|
||||
dest.write_char(' ')?;
|
||||
x.to_css(dest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for FontSettingTagInt {
|
||||
fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
if let Ok(value) = input.try(|input| input.expect_integer()) {
|
||||
// handle integer, throw if it is negative
|
||||
if value >= 0 {
|
||||
Ok(FontSettingTagInt(value as u32))
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) {
|
||||
// on is an alias for '1'
|
||||
Ok(FontSettingTagInt(1))
|
||||
} else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) {
|
||||
// off is an alias for '0'
|
||||
Ok(FontSettingTagInt(0))
|
||||
} else {
|
||||
// empty value is an alias for '1'
|
||||
Ok(FontSettingTagInt(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Parse for FontSettingTagFloat {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
|
||||
input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for FontSettingTagFloat {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
dest.write_str(" ")?;
|
||||
self.0.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper of Non-negative values.
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf)]
|
||||
|
@ -98,20 +98,26 @@ pub enum TimingFunction<Integer, Number> {
|
||||
Frames(Integer),
|
||||
}
|
||||
|
||||
define_css_keyword_enum! { TimingKeyword:
|
||||
"linear" => Linear,
|
||||
"ease" => Ease,
|
||||
"ease-in" => EaseIn,
|
||||
"ease-out" => EaseOut,
|
||||
"ease-in-out" => EaseInOut,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum TimingKeyword {
|
||||
Linear,
|
||||
Ease,
|
||||
EaseIn,
|
||||
EaseOut,
|
||||
EaseInOut,
|
||||
}
|
||||
add_impls_for_keyword_enum!(TimingKeyword);
|
||||
|
||||
define_css_keyword_enum! { StepPosition:
|
||||
"start" => Start,
|
||||
"end" => End,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum StepPosition {
|
||||
Start,
|
||||
End,
|
||||
}
|
||||
add_impls_for_keyword_enum!(StepPosition);
|
||||
|
||||
impl<H, V, D> TransformOrigin<H, V, D> {
|
||||
/// Returns a new transform origin.
|
||||
@ -714,3 +720,13 @@ pub enum Translate<LengthOrPercentage, Length> {
|
||||
/// '<length-percentage> <length-percentage> <length>'
|
||||
Translate3D(LengthOrPercentage, LengthOrPercentage, Length),
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
|
||||
pub enum TransformStyle {
|
||||
#[cfg(feature = "servo")]
|
||||
Auto,
|
||||
Flat,
|
||||
#[css(keyword = "preserve-3d")]
|
||||
Preserve3d,
|
||||
}
|
||||
|
@ -195,10 +195,14 @@ impl ToCss for KeyframesName {
|
||||
}
|
||||
}
|
||||
|
||||
// A type for possible values for min- and max- flavors of width,
|
||||
// height, block-size, and inline-size.
|
||||
define_css_keyword_enum!(ExtremumLength:
|
||||
"-moz-max-content" => MaxContent,
|
||||
"-moz-min-content" => MinContent,
|
||||
"-moz-fit-content" => FitContent,
|
||||
"-moz-available" => FillAvailable);
|
||||
/// A type for possible values for min- and max- flavors of width,
|
||||
/// height, block-size, and inline-size.
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum ExtremumLength {
|
||||
MozMaxContent,
|
||||
MozMinContent,
|
||||
MozFitContent,
|
||||
MozAvailable,
|
||||
}
|
||||
|
@ -28,9 +28,9 @@ pub enum Display {
|
||||
Table, InlineTable, TableRowGroup, TableHeaderGroup,
|
||||
TableFooterGroup, TableRow, TableColumnGroup,
|
||||
TableColumn, TableCell, TableCaption, ListItem, None,
|
||||
#[parse(aliases = "-webkit-flex")]
|
||||
#[css(aliases = "-webkit-flex")]
|
||||
Flex,
|
||||
#[parse(aliases = "-webkit-inline-flex")]
|
||||
#[css(aliases = "-webkit-inline-flex")]
|
||||
InlineFlex,
|
||||
#[cfg(feature = "gecko")]
|
||||
Grid,
|
||||
@ -320,25 +320,34 @@ impl Parse for AnimationName {
|
||||
}
|
||||
}
|
||||
|
||||
define_css_keyword_enum! { ScrollSnapType:
|
||||
"none" => None,
|
||||
"mandatory" => Mandatory,
|
||||
"proximity" => Proximity,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum ScrollSnapType {
|
||||
None,
|
||||
Mandatory,
|
||||
Proximity,
|
||||
}
|
||||
add_impls_for_keyword_enum!(ScrollSnapType);
|
||||
|
||||
define_css_keyword_enum! { OverscrollBehavior:
|
||||
"auto" => Auto,
|
||||
"contain" => Contain,
|
||||
"none" => None,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum OverscrollBehavior {
|
||||
Auto,
|
||||
Contain,
|
||||
None,
|
||||
}
|
||||
add_impls_for_keyword_enum!(OverscrollBehavior);
|
||||
|
||||
define_css_keyword_enum! { OverflowClipBox:
|
||||
"padding-box" => PaddingBox,
|
||||
"content-box" => ContentBox,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)]
|
||||
#[derive(ToComputedValue, ToCss)]
|
||||
pub enum OverflowClipBox {
|
||||
PaddingBox,
|
||||
ContentBox,
|
||||
}
|
||||
add_impls_for_keyword_enum!(OverflowClipBox);
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)]
|
||||
/// Provides a rendering hint to the user agent,
|
||||
|
@ -47,12 +47,13 @@ pub enum Color {
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
mod gecko {
|
||||
define_css_keyword_enum! { SpecialColorKeyword:
|
||||
"-moz-default-color" => MozDefaultColor,
|
||||
"-moz-default-background-color" => MozDefaultBackgroundColor,
|
||||
"-moz-hyperlinktext" => MozHyperlinktext,
|
||||
"-moz-activehyperlinktext" => MozActiveHyperlinktext,
|
||||
"-moz-visitedhyperlinktext" => MozVisitedHyperlinktext,
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss)]
|
||||
pub enum SpecialColorKeyword {
|
||||
MozDefaultColor,
|
||||
MozDefaultBackgroundColor,
|
||||
MozHyperlinktext,
|
||||
MozActiveHyperlinktext,
|
||||
MozVisitedHyperlinktext,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||
use values::CustomIdent;
|
||||
use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
|
||||
use values::computed::font::{SingleFontFamily, FontFamilyList, FamilyName};
|
||||
use values::generics::{FontSettings, FontSettingTagFloat};
|
||||
use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength, Number};
|
||||
use values::generics::font::{FontSettings, FeatureTagValue, VariationValue};
|
||||
use values::specified::{AllowQuirks, Integer, LengthOrPercentage, NoCalcLength, Number};
|
||||
use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize};
|
||||
|
||||
const DEFAULT_SCRIPT_MIN_SIZE_PT: u32 = 8;
|
||||
@ -164,8 +164,8 @@ impl From<LengthOrPercentage> for FontSize {
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies a prioritized list of font family names or generic family names.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
/// Specifies a prioritized list of font family names or generic family names
|
||||
pub enum FontFamily {
|
||||
/// List of `font-family`
|
||||
Values(FontFamilyList),
|
||||
@ -1709,13 +1709,15 @@ impl Parse for FontVariantNumeric {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone, Debug, PartialEq, ToCss)]
|
||||
/// Define initial settings that apply when the font defined
|
||||
/// by an @font-face rule is rendered.
|
||||
/// This property provides low-level control over OpenType or TrueType font variations.
|
||||
pub type SpecifiedFontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
|
||||
|
||||
/// Define initial settings that apply when the font defined by an @font-face
|
||||
/// rule is rendered.
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||
pub enum FontFeatureSettings {
|
||||
/// Value of `FontSettings`
|
||||
Value(computed::FontFeatureSettings),
|
||||
Value(SpecifiedFontFeatureSettings),
|
||||
/// System font
|
||||
System(SystemFont)
|
||||
}
|
||||
@ -1724,7 +1726,7 @@ impl FontFeatureSettings {
|
||||
#[inline]
|
||||
/// Get default value of `font-feature-settings` as normal
|
||||
pub fn normal() -> FontFeatureSettings {
|
||||
FontFeatureSettings::Value(FontSettings::Normal)
|
||||
FontFeatureSettings::Value(FontSettings::normal())
|
||||
}
|
||||
|
||||
/// Get `font-feature-settings` with system font
|
||||
@ -1745,12 +1747,12 @@ impl FontFeatureSettings {
|
||||
impl ToComputedValue for FontFeatureSettings {
|
||||
type ComputedValue = computed::FontFeatureSettings;
|
||||
|
||||
fn to_computed_value(&self, _context: &Context) -> computed::FontFeatureSettings {
|
||||
fn to_computed_value(&self, context: &Context) -> computed::FontFeatureSettings {
|
||||
match *self {
|
||||
FontFeatureSettings::Value(ref v) => v.clone(),
|
||||
FontFeatureSettings::Value(ref v) => v.to_computed_value(context),
|
||||
FontFeatureSettings::System(_) => {
|
||||
#[cfg(feature = "gecko")] {
|
||||
_context.cached_system_font.as_ref().unwrap().font_feature_settings.clone()
|
||||
context.cached_system_font.as_ref().unwrap().font_feature_settings.clone()
|
||||
}
|
||||
#[cfg(feature = "servo")] {
|
||||
unreachable!()
|
||||
@ -1760,7 +1762,7 @@ impl ToComputedValue for FontFeatureSettings {
|
||||
}
|
||||
|
||||
fn from_computed_value(other: &computed::FontFeatureSettings) -> Self {
|
||||
FontFeatureSettings::Value(other.clone())
|
||||
FontFeatureSettings::Value(ToComputedValue::from_computed_value(other))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1770,7 +1772,7 @@ impl Parse for FontFeatureSettings {
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<FontFeatureSettings, ParseError<'i>> {
|
||||
computed::FontFeatureSettings::parse(context, input).map(FontFeatureSettings::Value)
|
||||
SpecifiedFontFeatureSettings::parse(context, input).map(FontFeatureSettings::Value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1962,8 +1964,95 @@ impl Parse for FontLanguageOverride {
|
||||
}
|
||||
}
|
||||
|
||||
/// This property provides low-level control over OpenType or TrueType font variations.
|
||||
pub type FontVariantSettings = FontSettings<FontSettingTagFloat>;
|
||||
/// A font four-character tag, represented as a u32 for convenience.
|
||||
///
|
||||
/// See:
|
||||
/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def
|
||||
/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings
|
||||
///
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
pub struct FontTag(pub u32);
|
||||
|
||||
impl Parse for FontTag {
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
use byteorder::{ReadBytesExt, BigEndian};
|
||||
use std::io::Cursor;
|
||||
|
||||
let location = input.current_source_location();
|
||||
let tag = input.expect_string()?;
|
||||
|
||||
// allowed strings of length 4 containing chars: <U+20, U+7E>
|
||||
if tag.len() != 4 || tag.as_bytes().iter().any(|c| *c < b' ' || *c > b'~') {
|
||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
|
||||
let mut raw = Cursor::new(tag.as_bytes());
|
||||
Ok(FontTag(raw.read_u32::<BigEndian>().unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for FontTag {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use std::str;
|
||||
|
||||
let mut raw = [0u8; 4];
|
||||
BigEndian::write_u32(&mut raw, self.0);
|
||||
str::from_utf8(&raw).unwrap_or_default().to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
/// This property provides low-level control over OpenType or TrueType font
|
||||
/// variations.
|
||||
pub type FontVariationSettings = FontSettings<VariationValue<Number>>;
|
||||
|
||||
fn parse_one_feature_value<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Integer, ParseError<'i>> {
|
||||
if let Ok(integer) = input.try(|i| Integer::parse_non_negative(context, i)) {
|
||||
return Ok(integer)
|
||||
}
|
||||
|
||||
try_match_ident_ignore_ascii_case! { input,
|
||||
"on" => Ok(Integer::new(1)),
|
||||
"off" => Ok(Integer::new(0)),
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for FeatureTagValue<Integer> {
|
||||
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let tag = FontTag::parse(context, input)?;
|
||||
let value = input.try(|i| parse_one_feature_value(context, i))
|
||||
.unwrap_or_else(|_| Integer::new(1));
|
||||
|
||||
Ok(Self { tag, value })
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for VariationValue<Number> {
|
||||
/// This is the `<string> <number>` part of the font-variation-settings
|
||||
/// syntax.
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
let tag = FontTag::parse(context, input)?;
|
||||
let value = Number::parse(context, input)?;
|
||||
Ok(Self { tag, value })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
/// text-zoom. Enable if true, disable if false
|
||||
@ -2060,6 +2149,7 @@ pub enum MozScriptLevel {
|
||||
|
||||
impl Parse for MozScriptLevel {
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<MozScriptLevel, ParseError<'i>> {
|
||||
// We don't bother to handle calc here.
|
||||
if let Ok(i) = input.try(|i| i.expect_integer()) {
|
||||
return Ok(MozScriptLevel::Relative(i))
|
||||
}
|
||||
|
@ -825,8 +825,10 @@ impl LengthOrPercentage {
|
||||
/// Parse a length, treating dimensionless numbers as pixels
|
||||
///
|
||||
/// <https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value>
|
||||
pub fn parse_numbers_are_pixels<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
pub fn parse_numbers_are_pixels<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
|
||||
return Ok(lop)
|
||||
}
|
||||
@ -840,9 +842,10 @@ impl LengthOrPercentage {
|
||||
/// Parse a non-negative length, treating dimensionless numbers as pixels
|
||||
///
|
||||
/// This is nonstandard behavior used by Firefox for SVG
|
||||
pub fn parse_numbers_are_pixels_non_negative<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
pub fn parse_numbers_are_pixels_non_negative<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<LengthOrPercentage, ParseError<'i>> {
|
||||
if let Ok(lop) = input.try(|i| Self::parse_non_negative(context, i)) {
|
||||
return Ok(lop)
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
use Namespace;
|
||||
use context::QuirksMode;
|
||||
use cssparser::{Parser, Token, serialize_identifier};
|
||||
use num_traits::One;
|
||||
use parser::{ParserContext, Parse};
|
||||
use self::url::SpecifiedUrl;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
@ -33,7 +34,7 @@ pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||
pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
|
||||
pub use self::font::{FontFamily, FontLanguageOverride, FontVariationSettings, FontVariantEastAsian};
|
||||
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
|
||||
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
|
||||
pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior, Contain};
|
||||
@ -69,7 +70,8 @@ pub use self::table::XSpan;
|
||||
pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine};
|
||||
pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing};
|
||||
pub use self::time::Time;
|
||||
pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate, Scale};
|
||||
pub use self::transform::{Rotate, Scale, TimingFunction, Transform};
|
||||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
pub use self::ui::MozForceBrokenImageIcon;
|
||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||
|
||||
@ -160,20 +162,23 @@ fn parse_number_with_clamping_mode<'i, 't>(
|
||||
// 17.6.2.1. Higher values override lower values.
|
||||
//
|
||||
// FIXME(emilio): Should move to border.rs
|
||||
define_numbered_css_keyword_enum! { BorderStyle:
|
||||
"none" => None = -1,
|
||||
"solid" => Solid = 6,
|
||||
"double" => Double = 7,
|
||||
"dotted" => Dotted = 4,
|
||||
"dashed" => Dashed = 5,
|
||||
"hidden" => Hidden = -2,
|
||||
"groove" => Groove = 1,
|
||||
"ridge" => Ridge = 3,
|
||||
"inset" => Inset = 0,
|
||||
"outset" => Outset = 2,
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, Parse, PartialEq)]
|
||||
#[derive(PartialOrd, ToCss)]
|
||||
pub enum BorderStyle {
|
||||
None = -1,
|
||||
Solid = 6,
|
||||
Double = 7,
|
||||
Dotted = 4,
|
||||
Dashed = 5,
|
||||
Hidden = -2,
|
||||
Groove = 1,
|
||||
Ridge = 3,
|
||||
Inset = 0,
|
||||
Outset = 2,
|
||||
}
|
||||
|
||||
|
||||
impl BorderStyle {
|
||||
/// Whether this border style is either none or hidden.
|
||||
pub fn none_or_hidden(&self) -> bool {
|
||||
@ -382,12 +387,28 @@ impl ToComputedValue for Opacity {
|
||||
/// An specified `<integer>`, optionally coming from a `calc()` expression.
|
||||
///
|
||||
/// <https://drafts.csswg.org/css-values/#integers>
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
|
||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, PartialOrd)]
|
||||
pub struct Integer {
|
||||
value: CSSInteger,
|
||||
was_calc: bool,
|
||||
}
|
||||
|
||||
impl One for Integer {
|
||||
#[inline]
|
||||
fn one() -> Self {
|
||||
Self::new(1)
|
||||
}
|
||||
}
|
||||
|
||||
// This is not great, because it loses calc-ness, but it's necessary for One.
|
||||
impl ::std::ops::Mul<Integer> for Integer {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, other: Self) -> Self {
|
||||
Self::new(self.value * other.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
/// Trivially constructs a new `Integer` value.
|
||||
pub fn new(val: CSSInteger) -> Self {
|
||||
@ -435,7 +456,7 @@ impl Integer {
|
||||
pub fn parse_with_minimum<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
min: i32
|
||||
min: i32,
|
||||
) -> Result<Integer, ParseError<'i>> {
|
||||
match Integer::parse(context, input) {
|
||||
// FIXME(emilio): The spec asks us to avoid rejecting it at parse
|
||||
@ -498,10 +519,11 @@ impl ToCss for Integer {
|
||||
pub type IntegerOrAuto = Either<Integer, Auto>;
|
||||
|
||||
impl IntegerOrAuto {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_positive<'i, 't>(context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>)
|
||||
-> Result<IntegerOrAuto, ParseError<'i>> {
|
||||
/// Parse `auto` or a positive integer.
|
||||
pub fn parse_positive<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<IntegerOrAuto, ParseError<'i>> {
|
||||
match IntegerOrAuto::parse(context, input) {
|
||||
Ok(Either::First(integer)) if integer.value() <= 0 => {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
|
@ -39,10 +39,10 @@ impl OutlineStyle {
|
||||
|
||||
impl Parse for OutlineStyle {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>
|
||||
) -> Result<OutlineStyle, ParseError<'i>> {
|
||||
if let Ok(border_style) = input.try(|i| BorderStyle::parse(context, i)) {
|
||||
if let Ok(border_style) = input.try(BorderStyle::parse) {
|
||||
if let BorderStyle::Hidden = border_style {
|
||||
return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into())));
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ use values::specified::{self, Angle, Number, Length, Integer};
|
||||
use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
|
||||
use values::specified::position::{Side, X, Y};
|
||||
|
||||
pub use values::generics::transform::TransformStyle;
|
||||
|
||||
/// A single operation in a specified CSS `transform`
|
||||
pub type TransformOperation = GenericTransformOperation<
|
||||
Angle,
|
||||
|
@ -39,7 +39,7 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream {
|
||||
to_animated_value::derive(input).to_string().parse().unwrap()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Parse, attributes(parse))]
|
||||
#[proc_macro_derive(Parse, attributes(css))]
|
||||
pub fn derive_parse(stream: TokenStream) -> TokenStream {
|
||||
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
|
||||
parse::derive(input).to_string().parse().unwrap()
|
||||
|
@ -6,6 +6,7 @@ use cg;
|
||||
use quote::Tokens;
|
||||
use syn::DeriveInput;
|
||||
use synstructure;
|
||||
use to_css::CssVariantAttrs;
|
||||
|
||||
pub fn derive(input: DeriveInput) -> Tokens {
|
||||
let name = &input.ident;
|
||||
@ -19,8 +20,10 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||
"Parse is only supported for single-variant enums for now"
|
||||
);
|
||||
|
||||
let variant_attrs = cg::parse_variant_attrs::<ParseVariantAttrs>(variant);
|
||||
let identifier = cg::to_css_identifier(variant.ident.as_ref());
|
||||
let variant_attrs = cg::parse_variant_attrs::<CssVariantAttrs>(variant);
|
||||
let identifier = cg::to_css_identifier(
|
||||
&variant_attrs.keyword.as_ref().unwrap_or(&variant.ident).as_ref(),
|
||||
);
|
||||
let ident = &variant.ident;
|
||||
|
||||
match_body = quote! {
|
||||
@ -87,11 +90,3 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||
#methods_impl
|
||||
}
|
||||
}
|
||||
|
||||
#[darling(attributes(parse), default)]
|
||||
#[derive(Default, FromVariant)]
|
||||
struct ParseVariantAttrs {
|
||||
/// The comma-separated list of aliases this variant should be aliased to at
|
||||
/// parse time.
|
||||
aliases: Option<String>,
|
||||
}
|
||||
|
@ -23,10 +23,19 @@ pub fn derive(input: DeriveInput) -> Tokens {
|
||||
|
||||
if variant_attrs.dimension {
|
||||
assert_eq!(bindings.len(), 1);
|
||||
assert!(variant_attrs.function.is_none(), "That makes no sense");
|
||||
assert!(
|
||||
variant_attrs.function.is_none() && variant_attrs.keyword.is_none(),
|
||||
"That makes no sense"
|
||||
);
|
||||
}
|
||||
|
||||
let mut expr = if !bindings.is_empty() {
|
||||
let mut expr = if let Some(keyword) = variant_attrs.keyword {
|
||||
assert!(bindings.is_empty());
|
||||
let keyword = keyword.to_string();
|
||||
quote! {
|
||||
::std::fmt::Write::write_str(dest, #keyword)
|
||||
}
|
||||
} else if !bindings.is_empty() {
|
||||
let mut expr = quote! {};
|
||||
if variant_attrs.iterable {
|
||||
assert_eq!(bindings.len(), 1);
|
||||
@ -123,11 +132,13 @@ struct CssInputAttrs {
|
||||
|
||||
#[darling(attributes(css), default)]
|
||||
#[derive(Default, FromVariant)]
|
||||
struct CssVariantAttrs {
|
||||
function: Option<Function>,
|
||||
iterable: bool,
|
||||
comma: bool,
|
||||
dimension: bool,
|
||||
pub struct CssVariantAttrs {
|
||||
pub function: Option<Function>,
|
||||
pub iterable: bool,
|
||||
pub comma: bool,
|
||||
pub dimension: bool,
|
||||
pub keyword: Option<Ident>,
|
||||
pub aliases: Option<String>,
|
||||
}
|
||||
|
||||
#[darling(attributes(css), default)]
|
||||
@ -136,7 +147,7 @@ struct CssFieldAttrs {
|
||||
ignore_bound: bool,
|
||||
}
|
||||
|
||||
struct Function {
|
||||
pub struct Function {
|
||||
name: Option<Ident>,
|
||||
}
|
||||
|
||||
|
@ -384,69 +384,12 @@ impl_to_css_for_predefined_type!(::cssparser::UnicodeRange);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! define_css_keyword_enum {
|
||||
($name: ident: values { $( $css: expr => $variant: ident),+, }
|
||||
aliases { $( $alias: expr => $alias_variant: ident ),+, }) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),+ ]);
|
||||
};
|
||||
($name: ident: values { $( $css: expr => $variant: ident),+, }
|
||||
aliases { $( $alias: expr => $alias_variant: ident ),* }) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),* ]);
|
||||
};
|
||||
($name: ident: values { $( $css: expr => $variant: ident),+ }
|
||||
aliases { $( $alias: expr => $alias_variant: ident ),+, }) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),+ ]);
|
||||
};
|
||||
($name: ident: values { $( $css: expr => $variant: ident),+ }
|
||||
aliases { $( $alias: expr => $alias_variant: ident ),* }) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),* ]);
|
||||
};
|
||||
($name: ident: $( $css: expr => $variant: ident ),+,) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] []);
|
||||
};
|
||||
($name: ident: $( $css: expr => $variant: ident ),+) => {
|
||||
__define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] []);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
#[macro_export]
|
||||
macro_rules! __define_css_keyword_enum__add_optional_traits {
|
||||
($name: ident [ $( $css: expr => $variant: ident ),+ ]
|
||||
[ $( $alias: expr => $alias_variant: ident),* ]) => {
|
||||
__define_css_keyword_enum__actual! {
|
||||
$name [ Deserialize, Serialize, MallocSizeOf ]
|
||||
[ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),* ]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "servo"))]
|
||||
#[macro_export]
|
||||
macro_rules! __define_css_keyword_enum__add_optional_traits {
|
||||
($name: ident [ $( $css: expr => $variant: ident ),+ ]
|
||||
[ $( $alias: expr => $alias_variant: ident),* ]) => {
|
||||
__define_css_keyword_enum__actual! {
|
||||
$name [ MallocSizeOf ]
|
||||
[ $( $css => $variant ),+ ]
|
||||
[ $( $alias => $alias_variant ),* ]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __define_css_keyword_enum__actual {
|
||||
($name: ident [ $( $derived_trait: ident),* ]
|
||||
[ $( $css: expr => $variant: ident ),+ ]
|
||||
[ $( $alias: expr => $alias_variant: ident ),* ]) => {
|
||||
#[allow(non_camel_case_types, missing_docs)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq$(, $derived_trait )* )]
|
||||
(pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => {
|
||||
#[allow(missing_docs)]
|
||||
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
|
||||
pub enum $name {
|
||||
$( $variant ),+
|
||||
$($variant),+
|
||||
}
|
||||
|
||||
impl $name {
|
||||
@ -458,33 +401,40 @@ macro_rules! __define_css_keyword_enum__actual {
|
||||
match *input.next()? {
|
||||
Token::Ident(ref ident) => {
|
||||
Self::from_ident(ident).map_err(|()| {
|
||||
location.new_unexpected_token_error(Token::Ident(ident.clone()))
|
||||
location.new_unexpected_token_error(
|
||||
Token::Ident(ident.clone()),
|
||||
)
|
||||
})
|
||||
}
|
||||
ref token => Err(location.new_unexpected_token_error(token.clone()))
|
||||
ref token => {
|
||||
Err(location.new_unexpected_token_error(token.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse this property from an already-tokenized identifier.
|
||||
pub fn from_ident(ident: &str) -> Result<$name, ()> {
|
||||
match_ignore_ascii_case! { ident,
|
||||
$( $css => Ok($name::$variant), )+
|
||||
$( $alias => Ok($name::$alias_variant), )*
|
||||
_ => Err(())
|
||||
$($css => Ok($name::$variant),)+
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::ToCss for $name {
|
||||
fn to_css<W>(&self, dest: &mut $crate::CssWriter<W>) -> ::std::fmt::Result
|
||||
where W: ::std::fmt::Write
|
||||
fn to_css<W>(
|
||||
&self,
|
||||
dest: &mut $crate::CssWriter<W>,
|
||||
) -> ::std::fmt::Result
|
||||
where
|
||||
W: ::std::fmt::Write,
|
||||
{
|
||||
match *self {
|
||||
$( $name::$variant => ::std::fmt::Write::write_str(dest, $css) ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Helper types for the handling of specified values.
|
||||
|
@ -10,14 +10,20 @@ use euclid::TypedSize2D;
|
||||
#[allow(unused_imports)] use std::ascii::AsciiExt;
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
define_css_keyword_enum!(UserZoom:
|
||||
"zoom" => Zoom,
|
||||
"fixed" => Fixed);
|
||||
define_css_keyword_enum! {
|
||||
pub enum UserZoom {
|
||||
Zoom = "zoom",
|
||||
Fixed = "fixed",
|
||||
}
|
||||
}
|
||||
|
||||
define_css_keyword_enum!(Orientation:
|
||||
"auto" => Auto,
|
||||
"portrait" => Portrait,
|
||||
"landscape" => Landscape);
|
||||
define_css_keyword_enum! {
|
||||
pub enum Orientation {
|
||||
Auto = "auto",
|
||||
Portrait = "portrait",
|
||||
Landscape = "landscape",
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of viewport descriptors:
|
||||
///
|
||||
|
@ -4727,10 +4727,11 @@ pub extern "C" fn Servo_ParseFontDescriptor(
|
||||
) -> bool {
|
||||
use cssparser::UnicodeRange;
|
||||
use self::nsCSSFontDesc::*;
|
||||
use style::computed_values::{font_feature_settings, font_stretch, font_style};
|
||||
use style::computed_values::{font_stretch, font_style};
|
||||
use style::font_face::{FontDisplay, FontWeight, Source};
|
||||
use style::properties::longhands::font_language_override;
|
||||
use style::values::computed::font::FamilyName;
|
||||
use style::values::specified::font::SpecifiedFontFeatureSettings;
|
||||
|
||||
let string = unsafe { (*value).to_string() };
|
||||
let mut input = ParserInput::new(&string);
|
||||
@ -4779,7 +4780,7 @@ pub extern "C" fn Servo_ParseFontDescriptor(
|
||||
eCSSFontDesc_Stretch / font_stretch::T,
|
||||
eCSSFontDesc_Src / Vec<Source>,
|
||||
eCSSFontDesc_UnicodeRange / Vec<UnicodeRange>,
|
||||
eCSSFontDesc_FontFeatureSettings / font_feature_settings::T,
|
||||
eCSSFontDesc_FontFeatureSettings / SpecifiedFontFeatureSettings,
|
||||
eCSSFontDesc_FontLanguageOverride / font_language_override::SpecifiedValue,
|
||||
eCSSFontDesc_Display / FontDisplay,
|
||||
]
|
||||
|
@ -168,16 +168,16 @@ fn border_image_outset_should_return_length_on_length_zero() {
|
||||
fn test_border_style() {
|
||||
use style::values::specified::BorderStyle;
|
||||
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"none"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"hidden"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"solid"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"double"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"dotted"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"dashed"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"groove"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"ridge"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"inset"#);
|
||||
assert_roundtrip_with_context!(BorderStyle::parse, r#"outset"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"none"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"hidden"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"solid"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"double"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dotted"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"dashed"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"groove"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"ridge"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"inset"#);
|
||||
assert_roundtrip_with_context!(<BorderStyle as Parse>::parse, r#"outset"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -3,7 +3,7 @@ use logging;
|
||||
use logging::LogLevel;
|
||||
use mozprofile::preferences::Pref;
|
||||
use mozprofile::profile::Profile;
|
||||
use mozrunner::runner::{Runner, FirefoxRunner};
|
||||
use mozrunner::runner::{FirefoxRunner, FirefoxProcess, Runner, RunnerProcess};
|
||||
use regex::Captures;
|
||||
use rustc_serialize::base64::FromBase64;
|
||||
use rustc_serialize::json;
|
||||
@ -391,7 +391,7 @@ pub struct MarionetteSettings {
|
||||
pub struct MarionetteHandler {
|
||||
connection: Mutex<Option<MarionetteConnection>>,
|
||||
settings: MarionetteSettings,
|
||||
browser: Option<FirefoxRunner>,
|
||||
browser: Option<FirefoxProcess>,
|
||||
current_log_level: Option<LogLevel>,
|
||||
}
|
||||
|
||||
@ -438,45 +438,49 @@ impl MarionetteHandler {
|
||||
Ok(capabilities)
|
||||
}
|
||||
|
||||
fn start_browser(&mut self, port: u16, mut options: FirefoxOptions) -> WebDriverResult<()> {
|
||||
let binary = try!(options.binary
|
||||
fn start_browser(&mut self, port: u16, options: FirefoxOptions) -> WebDriverResult<()> {
|
||||
let binary = options.binary
|
||||
.ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated,
|
||||
"Expected browser binary location, but unable to find \
|
||||
binary in default location, no \
|
||||
'moz:firefoxOptions.binary' capability provided, and \
|
||||
no binary flag set on the command line")));
|
||||
no binary flag set on the command line"))?;
|
||||
|
||||
let custom_profile = options.profile.is_some();
|
||||
let is_custom_profile = options.profile.is_some();
|
||||
|
||||
let mut runner = try!(FirefoxRunner::new(&binary, options.profile.take())
|
||||
.map_err(|e| WebDriverError::new(ErrorStatus::SessionNotCreated,
|
||||
e.description().to_owned())));
|
||||
|
||||
// double-dashed flags are not accepted on Windows systems
|
||||
runner.args().push("-marionette".to_owned());
|
||||
|
||||
// https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
|
||||
runner.envs().insert("MOZ_CRASHREPORTER".to_string(), "1".to_string());
|
||||
runner.envs().insert("MOZ_CRASHREPORTER_NO_REPORT".to_string(), "1".to_string());
|
||||
runner.envs().insert("MOZ_CRASHREPORTER_SHUTDOWN".to_string(), "1".to_string());
|
||||
|
||||
if let Some(args) = options.args.take() {
|
||||
runner.args().extend(args);
|
||||
let mut profile = match options.profile {
|
||||
Some(x) => x,
|
||||
None => Profile::new(None)?
|
||||
};
|
||||
|
||||
try!(self.set_prefs(port, &mut runner.profile, custom_profile, options.prefs)
|
||||
self.set_prefs(port, &mut profile, is_custom_profile, options.prefs)
|
||||
.map_err(|e| {
|
||||
WebDriverError::new(ErrorStatus::SessionNotCreated,
|
||||
format!("Failed to set preferences: {}", e))
|
||||
}));
|
||||
})?;
|
||||
|
||||
try!(runner.start()
|
||||
|
||||
let mut runner = FirefoxRunner::new(&binary, profile);
|
||||
|
||||
runner
|
||||
// double-dashed flags are not accepted on Windows systems
|
||||
.arg("-marionette")
|
||||
// https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
|
||||
.env("MOZ_CRASHREPORTER", "1")
|
||||
.env("MOZ_CRASHREPORTER_NO_REPORT", "1")
|
||||
.env("MOZ_CRASHREPORTER_SHUTDOWN", "1");
|
||||
|
||||
if let Some(args) = options.args.as_ref() {
|
||||
runner.args(args);
|
||||
};
|
||||
|
||||
let browser_proc = runner.start()
|
||||
.map_err(|e| {
|
||||
WebDriverError::new(ErrorStatus::SessionNotCreated,
|
||||
format!("Failed to start browser {}: {}",
|
||||
binary.display(), e))
|
||||
}));
|
||||
self.browser = Some(runner);
|
||||
})?;
|
||||
self.browser = Some(browser_proc);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -1336,7 +1340,7 @@ impl MarionetteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect(&mut self, browser: &mut Option<FirefoxRunner>) -> WebDriverResult<()> {
|
||||
pub fn connect(&mut self, browser: &mut Option<FirefoxProcess>) -> WebDriverResult<()> {
|
||||
let timeout = 60 * 1000; // ms
|
||||
let poll_interval = 100; // ms
|
||||
let poll_attempts = timeout / poll_interval;
|
||||
|
@ -48,7 +48,7 @@ class TestMarionette(MarionetteTestCase):
|
||||
self.assertRaises(socket.timeout, marionette.raise_for_port, timeout=1.0)
|
||||
|
||||
self.marionette._send_message("acceptConnections", {"value": True})
|
||||
marionette.raise_for_port(timeout=1.0)
|
||||
marionette.raise_for_port(timeout=10.0)
|
||||
|
||||
finally:
|
||||
self.marionette._send_message("acceptConnections", {"value": True})
|
||||
|
@ -5,20 +5,51 @@ use std::collections::HashMap;
|
||||
use std::convert::From;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::fmt;
|
||||
use std::io::{Result as IoResult, Error as IoError, ErrorKind};
|
||||
use std::io::{Error as IoError, ErrorKind, Result as IoResult};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Child, Command, Stdio};
|
||||
use std::process;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
pub trait Runner {
|
||||
fn args(&mut self) -> &mut Vec<String>;
|
||||
fn build_command(&self, &mut Command);
|
||||
fn envs(&mut self) -> &mut HashMap<String, String>;
|
||||
fn is_running(&mut self) -> bool;
|
||||
fn start(&mut self) -> Result<(), RunnerError>;
|
||||
type Process;
|
||||
|
||||
fn arg<'a, S>(&'a mut self, arg: S) -> &'a mut Self
|
||||
where
|
||||
S: AsRef<OsStr>;
|
||||
|
||||
fn args<'a, I, S>(&'a mut self, args: I) -> &'a mut Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>;
|
||||
|
||||
fn env<'a, K, V>(&'a mut self, key: K, value: V) -> &'a mut Self
|
||||
where
|
||||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>;
|
||||
|
||||
fn envs<'a, I, K, V>(&'a mut self, envs: I) -> &'a mut Self
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>;
|
||||
|
||||
fn stdout<'a, T>(&'a mut self, stdout: T) -> &'a mut Self
|
||||
where
|
||||
T: Into<Stdio>;
|
||||
|
||||
fn stderr<'a, T>(&'a mut self, stderr: T) -> &'a mut Self
|
||||
where
|
||||
T: Into<Stdio>;
|
||||
|
||||
fn start(self) -> Result<Self::Process, RunnerError>;
|
||||
}
|
||||
|
||||
pub trait RunnerProcess {
|
||||
fn status(&mut self) -> IoResult<Option<process::ExitStatus>>;
|
||||
fn stop(&mut self) -> IoResult<Option<process::ExitStatus>>;
|
||||
fn stop(&mut self) -> IoResult<process::ExitStatus>;
|
||||
fn is_running(&mut self) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -66,94 +97,150 @@ impl From<PrefReaderError> for RunnerError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FirefoxProcess {
|
||||
process: Child,
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
impl RunnerProcess for FirefoxProcess {
|
||||
fn status(&mut self) -> IoResult<Option<process::ExitStatus>> {
|
||||
self.process.try_wait()
|
||||
}
|
||||
|
||||
fn is_running(&mut self) -> bool {
|
||||
self.status().unwrap().is_none()
|
||||
}
|
||||
|
||||
fn stop(&mut self) -> IoResult<process::ExitStatus> {
|
||||
self.process.kill()?;
|
||||
self.process.wait()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FirefoxRunner {
|
||||
pub binary: PathBuf,
|
||||
args: Vec<String>,
|
||||
envs: HashMap<String, String>,
|
||||
process: Option<process::Child>,
|
||||
pub profile: Profile
|
||||
binary: PathBuf,
|
||||
profile: Profile,
|
||||
args: Vec<OsString>,
|
||||
envs: HashMap<OsString, OsString>,
|
||||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
}
|
||||
|
||||
impl FirefoxRunner {
|
||||
pub fn new(binary: &Path, profile: Option<Profile>) -> IoResult<FirefoxRunner> {
|
||||
let prof = match profile {
|
||||
Some(p) => p,
|
||||
None => try!(Profile::new(None))
|
||||
};
|
||||
pub fn new(binary: &Path, profile: Profile) -> FirefoxRunner {
|
||||
let mut envs: HashMap<OsString, OsString> = HashMap::new();
|
||||
envs.insert("MOZ_NO_REMOTE".into(), "1".into());
|
||||
envs.insert("NO_EM_RESTART".into(), "1".into());
|
||||
|
||||
let mut envs = HashMap::new();
|
||||
envs.insert("MOZ_NO_REMOTE".to_string(), "1".to_string());
|
||||
envs.insert("NO_EM_RESTART".to_string(), "1".to_string());
|
||||
|
||||
Ok(FirefoxRunner {
|
||||
FirefoxRunner {
|
||||
binary: binary.to_path_buf(),
|
||||
process: None,
|
||||
args: Vec::new(),
|
||||
envs: envs,
|
||||
profile: prof
|
||||
})
|
||||
profile: profile,
|
||||
args: vec![],
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Runner for FirefoxRunner {
|
||||
fn args(&mut self) -> &mut Vec<String> {
|
||||
&mut self.args
|
||||
type Process = FirefoxProcess;
|
||||
|
||||
fn arg<'a, S>(&'a mut self, arg: S) -> &'a mut FirefoxRunner
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
self.args.push((&arg).into());
|
||||
self
|
||||
}
|
||||
|
||||
fn build_command(&self, command: &mut Command) {
|
||||
command
|
||||
.args(&self.args[..])
|
||||
.envs(&self.envs);
|
||||
fn args<'a, I, S>(&'a mut self, args: I) -> &'a mut FirefoxRunner
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
for arg in args {
|
||||
self.args.push((&arg).into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn env<'a, K, V>(&'a mut self, key: K, value: V) -> &'a mut FirefoxRunner
|
||||
where
|
||||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>,
|
||||
{
|
||||
self.envs.insert((&key).into(), (&value).into());
|
||||
self
|
||||
}
|
||||
|
||||
fn envs<'a, I, K, V>(&'a mut self, envs: I) -> &'a mut FirefoxRunner
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>,
|
||||
{
|
||||
for (key, value) in envs {
|
||||
self.envs.insert((&key).into(), (&value).into());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn stdout<'a, T>(&'a mut self, stdout: T) -> &'a mut Self
|
||||
where
|
||||
T: Into<Stdio>,
|
||||
{
|
||||
self.stdout = Some(stdout.into());
|
||||
self
|
||||
}
|
||||
|
||||
fn stderr<'a, T>(&'a mut self, stderr: T) -> &'a mut Self
|
||||
where
|
||||
T: Into<Stdio>,
|
||||
{
|
||||
self.stderr = Some(stderr.into());
|
||||
self
|
||||
}
|
||||
|
||||
fn start(mut self) -> Result<FirefoxProcess, RunnerError> {
|
||||
let stdout = self.stdout.unwrap_or_else(|| Stdio::inherit());
|
||||
let stderr = self.stderr.unwrap_or_else(|| Stdio::inherit());
|
||||
|
||||
let mut cmd = Command::new(&self.binary);
|
||||
cmd.args(&self.args[..])
|
||||
.envs(&self.envs)
|
||||
.stdout(stdout)
|
||||
.stderr(stderr);
|
||||
|
||||
if !self.args.iter().any(|x| is_profile_arg(x)) {
|
||||
command.arg("-profile").arg(&self.profile.path);
|
||||
cmd.arg("-profile").arg(&self.profile.path);
|
||||
}
|
||||
command.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit());
|
||||
}
|
||||
cmd.stdout(Stdio::inherit()).stderr(Stdio::inherit());
|
||||
|
||||
fn envs(&mut self) -> &mut HashMap<String, String> {
|
||||
&mut self.envs
|
||||
}
|
||||
|
||||
fn is_running(&mut self) -> bool {
|
||||
self.process.is_some() && self.status().unwrap().is_none()
|
||||
}
|
||||
|
||||
fn start(&mut self) -> Result<(), RunnerError> {
|
||||
let mut cmd = Command::new(&self.binary);
|
||||
self.build_command(&mut cmd);
|
||||
|
||||
let prefs = try!(self.profile.user_prefs());
|
||||
try!(prefs.write());
|
||||
self.profile.user_prefs()?.write()?;
|
||||
|
||||
info!("Running command: {:?}", cmd);
|
||||
let process = try!(cmd.spawn());
|
||||
self.process = Some(process);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn status(&mut self) -> IoResult<Option<process::ExitStatus>> {
|
||||
self.process.as_mut().map(|p| p.try_wait()).unwrap_or(Ok(None))
|
||||
}
|
||||
|
||||
fn stop(&mut self) -> IoResult<Option<process::ExitStatus>> {
|
||||
let mut retval = None;
|
||||
|
||||
if let Some(ref mut p) = self.process {
|
||||
try!(p.kill());
|
||||
retval = Some(try!(p.wait()));
|
||||
};
|
||||
Ok(retval)
|
||||
let process = cmd.spawn()?;
|
||||
Ok(FirefoxProcess {
|
||||
process: process,
|
||||
profile: self.profile
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_arg_name(arg: &str) -> Option<&str> {
|
||||
fn parse_arg_name<T>(arg: T) -> Option<String>
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
{
|
||||
let arg_os_str: &OsStr = arg.as_ref();
|
||||
let arg_str = arg_os_str.to_string_lossy();
|
||||
|
||||
let mut start = 0;
|
||||
let mut end = 0;
|
||||
|
||||
for (i, c) in arg.chars().enumerate() {
|
||||
for (i, c) in arg_str.chars().enumerate() {
|
||||
if i == 0 {
|
||||
if !platform::arg_prefix_char(c) {
|
||||
break;
|
||||
@ -178,7 +265,7 @@ fn parse_arg_name(arg: &str) -> Option<&str> {
|
||||
}
|
||||
|
||||
if start > 0 && end > start {
|
||||
Some(&arg[start..end])
|
||||
Some(arg_str[start..end].into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -193,28 +280,28 @@ fn name_end_char(c: char) -> bool {
|
||||
/// Returns a boolean indicating whether a given string
|
||||
/// contains one of the `-P`, `-Profile` or `-ProfileManager`
|
||||
/// arguments, respecting the various platform-specific conventions.
|
||||
pub fn is_profile_arg(arg: &str) -> bool {
|
||||
pub fn is_profile_arg<T>(arg: T) -> bool
|
||||
where
|
||||
T: AsRef<OsStr>,
|
||||
{
|
||||
if let Some(name) = parse_arg_name(arg) {
|
||||
name.eq_ignore_ascii_case("profile") ||
|
||||
name.eq_ignore_ascii_case("p") ||
|
||||
name.eq_ignore_ascii_case("profilemanager")
|
||||
name.eq_ignore_ascii_case("profile") || name.eq_ignore_ascii_case("p")
|
||||
|| name.eq_ignore_ascii_case("profilemanager")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn find_binary(name: &str) -> Option<PathBuf> {
|
||||
env::var("PATH")
|
||||
.ok()
|
||||
.and_then(|path_env| {
|
||||
for mut path in env::split_paths(&*path_env) {
|
||||
path.push(name);
|
||||
if path.exists() {
|
||||
return Some(path)
|
||||
}
|
||||
env::var("PATH").ok().and_then(|path_env| {
|
||||
for mut path in env::split_paths(&*path_env) {
|
||||
path.push(name);
|
||||
if path.exists() {
|
||||
return Some(path);
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -239,19 +326,24 @@ pub mod platform {
|
||||
|
||||
pub fn firefox_default_path() -> Option<PathBuf> {
|
||||
if let Some(path) = find_binary("firefox-bin") {
|
||||
return Some(path)
|
||||
return Some(path);
|
||||
}
|
||||
let home = env::home_dir();
|
||||
for &(prefix_home, trial_path) in [
|
||||
(false, "/Applications/Firefox.app/Contents/MacOS/firefox-bin"),
|
||||
(true, "Applications/Firefox.app/Contents/MacOS/firefox-bin")].iter() {
|
||||
(
|
||||
false,
|
||||
"/Applications/Firefox.app/Contents/MacOS/firefox-bin",
|
||||
),
|
||||
(true, "Applications/Firefox.app/Contents/MacOS/firefox-bin"),
|
||||
].iter()
|
||||
{
|
||||
let path = match (home.as_ref(), prefix_home) {
|
||||
(Some(ref home_dir), true) => home_dir.join(trial_path),
|
||||
(None, true) => continue,
|
||||
(_, false) => PathBuf::from(trial_path)
|
||||
(_, false) => PathBuf::from(trial_path),
|
||||
};
|
||||
if path.exists() {
|
||||
return Some(path)
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -274,7 +366,7 @@ pub mod platform {
|
||||
let opt_path = firefox_registry_path().unwrap_or(None);
|
||||
if let Some(path) = opt_path {
|
||||
if path.exists() {
|
||||
return Some(path)
|
||||
return Some(path);
|
||||
}
|
||||
};
|
||||
find_binary("firefox.exe")
|
||||
@ -301,7 +393,7 @@ pub mod platform {
|
||||
if let Ok(bin_subtree) = mozilla.open_subkey_with_flags(bin_key, KEY_READ) {
|
||||
let path: Result<String, _> = bin_subtree.get_value("PathToExe");
|
||||
if let Ok(path) = path {
|
||||
return Ok(Some(PathBuf::from(path)))
|
||||
return Ok(Some(PathBuf::from(path)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,11 +423,11 @@ pub mod platform {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{parse_arg_name, is_profile_arg};
|
||||
use super::{is_profile_arg, parse_arg_name};
|
||||
|
||||
fn parse(arg: &str, name: Option<&str>) {
|
||||
let result = parse_arg_name(arg);
|
||||
assert_eq!(result, name);
|
||||
assert_eq!(result, name.map(|x| x.to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2000,7 +2000,8 @@ or run without that action (ie: --no-{action})"
|
||||
yield filter_alert({
|
||||
"name": "installer size",
|
||||
"value": installer_size,
|
||||
"alertThreshold": 1.0,
|
||||
"alertChangeType": "absolute",
|
||||
"alertThreshold": (100 * 1024),
|
||||
"subtests": size_measurements
|
||||
})
|
||||
|
||||
|
@ -214,10 +214,12 @@ def gl_provider_define(provider):
|
||||
|
||||
set_define('MOZ_GL_PROVIDER', gl_provider_define)
|
||||
|
||||
@depends(gl_provider, x11)
|
||||
def gl_default_provider(value, x11):
|
||||
@depends(gl_provider, wayland, x11)
|
||||
def gl_default_provider(value, wayland, x11):
|
||||
if value:
|
||||
return value
|
||||
elif wayland:
|
||||
return 'EGL'
|
||||
elif x11:
|
||||
return 'GLX'
|
||||
|
||||
|
@ -47,6 +47,7 @@ const PREF_BLOCKLIST_LASTUPDATETIME = "app.update.lastUpdateTime.blocklist-bac
|
||||
const PREF_BLOCKLIST_URL = "extensions.blocklist.url";
|
||||
const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
|
||||
const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
|
||||
const PREF_BLOCKLIST_LAST_MODIFIED = "extensions.blocklist.lastModified";
|
||||
const PREF_BLOCKLIST_LEVEL = "extensions.blocklist.level";
|
||||
const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal";
|
||||
const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
|
||||
@ -579,7 +580,15 @@ Blocklist.prototype = {
|
||||
request.open("GET", uri.spec, true);
|
||||
request.channel.notificationCallbacks = new gCertUtils.BadCertHandler();
|
||||
request.overrideMimeType("text/xml");
|
||||
request.setRequestHeader("Cache-Control", "no-cache");
|
||||
|
||||
// The server will return a `304 Not Modified` response if the blocklist was
|
||||
// not changed since last check.
|
||||
const lastModified = Services.prefs.getCharPref(PREF_BLOCKLIST_LAST_MODIFIED, "");
|
||||
if (lastModified) {
|
||||
request.setRequestHeader("If-Modified-Since", lastModified);
|
||||
} else {
|
||||
request.setRequestHeader("Cache-Control", "no-cache");
|
||||
}
|
||||
|
||||
request.addEventListener("error", event => this.onXMLError(event));
|
||||
request.addEventListener("load", event => this.onXMLLoad(event));
|
||||
@ -607,6 +616,12 @@ Blocklist.prototype = {
|
||||
LOG("Blocklist::onXMLLoad: " + e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.status == 304) {
|
||||
LOG("Blocklist::onXMLLoad: up to date.");
|
||||
return;
|
||||
}
|
||||
|
||||
let responseXML = request.responseXML;
|
||||
if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR ||
|
||||
(request.status != 200 && request.status != 0)) {
|
||||
@ -614,6 +629,10 @@ Blocklist.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save current blocklist timestamp to pref.
|
||||
const lastModified = request.getResponseHeader("Last-Modified") || "";
|
||||
Services.prefs.setCharPref(PREF_BLOCKLIST_LAST_MODIFIED, lastModified);
|
||||
|
||||
var oldAddonEntries = this._addonEntries;
|
||||
var oldPluginEntries = this._pluginEntries;
|
||||
this._addonEntries = [];
|
||||
|
Loading…
Reference in New Issue
Block a user