Bug 657953 (1/2) - Implement the layout part of the meter element. r=roc
authorVincent LAMOTTE <Vincent.Lamotte@ensimag.imag.fr>
Wed, 16 May 2012 17:47:10 +0200
changeset 100741 1774f76e6867219e43248d99c67f447f2ff43806
parent 100740 c2686a37ae6458d54d3032d73b8aadad67758ae1
child 100742 30a518ac406f61200ed4468202947ebf940dd2e4
push id1316
push userakeybl@mozilla.com
push dateMon, 27 Aug 2012 22:37:00 +0000
treeherdermozilla-beta@db4b09302ee2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs657953
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 657953 (1/2) - Implement the layout part of the meter element. r=roc
layout/base/nsCSSFrameConstructor.cpp
layout/forms/Makefile.in
layout/forms/nsMeterFrame.cpp
layout/forms/nsMeterFrame.h
layout/generic/nsHTMLParts.h
layout/generic/nsQueryFrame.h
layout/style/forms.css
layout/style/nsCSSPseudoElementList.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3373,17 +3373,18 @@ nsCSSFrameConstructor::FindHTMLData(Elem
       FCDATA_WITH_WRAPPING_BLOCK(FCDATA_ALLOW_BLOCK_STYLES,
                                  NS_NewHTMLButtonControlFrame,
                                  nsCSSAnonBoxes::buttonContent) },
     SIMPLE_TAG_CHAIN(canvas, nsCSSFrameConstructor::FindCanvasData),
 #if defined(MOZ_MEDIA)
     SIMPLE_TAG_CREATE(video, NS_NewHTMLVideoFrame),
     SIMPLE_TAG_CREATE(audio, NS_NewHTMLVideoFrame),
 #endif
-    SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame)
+    SIMPLE_TAG_CREATE(progress, NS_NewProgressFrame),
+    SIMPLE_TAG_CREATE(meter, NS_NewMeterFrame)
   };
 
   return FindDataByTag(aTag, aElement, aStyleContext, sHTMLData,
                        ArrayLength(sHTMLData));
 }
 
 /* static */
 const nsCSSFrameConstructor::FrameConstructionData*
--- a/layout/forms/Makefile.in
+++ b/layout/forms/Makefile.in
@@ -34,16 +34,17 @@ CPPSRCS		= \
 		nsComboboxControlFrame.cpp \
 		nsFieldSetFrame.cpp \
 		nsFileControlFrame.cpp \
 		nsFormControlFrame.cpp \
 		nsGfxButtonControlFrame.cpp \
 		nsGfxCheckboxControlFrame.cpp \
 		nsGfxRadioControlFrame.cpp \
 		nsProgressFrame.cpp \
+		nsMeterFrame.cpp \
 		nsTextControlFrame.cpp \
 		nsHTMLButtonControlFrame.cpp \
 		nsImageControlFrame.cpp \
 		nsLegendFrame.cpp \
 		nsListControlFrame.cpp \
 		nsSelectsAreaFrame.cpp \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/layout/forms/nsMeterFrame.cpp
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mounir Lamouri <mounir.lamouri@mozilla.com>
+ *   Vincent Lamotte <Vincent.Lamotte@ensimag.imag.fr>
+ *   Laurent Dulary <Laurent.Dulary@ensimag.imag.fr>
+ *   Yoan Teboul <Yoan.Teboul@ensimag.imag.fr>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMeterFrame.h"
+
+#include "nsIDOMHTMLMeterElement.h"
+#include "nsIContent.h"
+#include "prtypes.h"
+#include "nsPresContext.h"
+#include "nsGkAtoms.h"
+#include "nsINameSpaceManager.h"
+#include "nsIDocument.h"
+#include "nsIPresShell.h"
+#include "nsNodeInfoManager.h"
+#include "nsINodeInfo.h"
+#include "nsContentCreatorFunctions.h"
+#include "nsContentUtils.h"
+#include "nsFormControlFrame.h"
+#include "nsFontMetrics.h"
+#include "mozilla/dom/Element.h"
+
+
+nsIFrame*
+NS_NewMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
+{
+  return new (aPresShell) nsMeterFrame(aContext);
+}
+
+NS_IMPL_FRAMEARENA_HELPERS(nsMeterFrame)
+
+nsMeterFrame::nsMeterFrame(nsStyleContext* aContext)
+  : nsContainerFrame(aContext)
+  , mBarDiv(nsnull)
+{
+}
+
+nsMeterFrame::~nsMeterFrame()
+{
+}
+
+void
+nsMeterFrame::DestroyFrom(nsIFrame* aDestructRoot)
+{
+  NS_ASSERTION(!GetPrevContinuation(),
+               "nsMeterFrame should not have continuations; if it does we "
+               "need to call RegUnregAccessKey only for the first.");
+  nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
+  nsContentUtils::DestroyAnonymousContent(&mBarDiv);
+  nsContainerFrame::DestroyFrom(aDestructRoot);
+}
+
+nsresult
+nsMeterFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
+{
+  // Get the NodeInfoManager and tag necessary to create the meter bar div.
+  nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
+
+  nsCOMPtr<nsINodeInfo> nodeInfo;
+  nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::div, nsnull,
+                                                 kNameSpaceID_XHTML,
+                                                 nsIDOMNode::ELEMENT_NODE);
+  NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
+
+  // Create the div.
+  nsresult rv = NS_NewHTMLElement(getter_AddRefs(mBarDiv), nodeInfo.forget(),
+                                  mozilla::dom::NOT_FROM_PARSER);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Associate ::-moz-meter-bar pseudo-element to the anonymous child.
+  nsCSSPseudoElements::Type pseudoType = nsCSSPseudoElements::ePseudo_mozMeterBar;
+  nsRefPtr<nsStyleContext> newStyleContext = PresContext()->StyleSet()->
+    ResolvePseudoElementStyle(mContent->AsElement(), pseudoType,
+                              GetStyleContext());
+
+  if (!aElements.AppendElement(ContentInfo(mBarDiv, newStyleContext))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return NS_OK;
+}
+
+void
+nsMeterFrame::AppendAnonymousContentTo(nsBaseContentList& aElements,
+                                       PRUint32 aFilter)
+{
+  aElements.MaybeAppendElement(mBarDiv);
+}
+
+NS_QUERYFRAME_HEAD(nsMeterFrame)
+  NS_QUERYFRAME_ENTRY(nsMeterFrame)
+  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
+NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
+
+
+NS_IMETHODIMP nsMeterFrame::Reflow(nsPresContext*           aPresContext,
+                                   nsHTMLReflowMetrics&     aDesiredSize,
+                                   const nsHTMLReflowState& aReflowState,
+                                   nsReflowStatus&          aStatus)
+{
+  DO_GLOBAL_REFLOW_COUNT("nsMeterFrame");
+  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
+
+  NS_ASSERTION(mBarDiv, "Meter bar div must exist!");
+  NS_ASSERTION(!GetPrevContinuation(),
+               "nsMeterFrame should not have continuations; if it does we "
+               "need to call RegUnregAccessKey only for the first.");
+
+  if (mState & NS_FRAME_FIRST_REFLOW) {
+    nsFormControlFrame::RegUnRegAccessKey(this, true);
+  }
+
+  nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
+  NS_ASSERTION(barFrame, "The meter frame should have a child with a frame!");
+
+  ReflowBarFrame(barFrame, aPresContext, aReflowState, aStatus);
+
+  aDesiredSize.width = aReflowState.ComputedWidth() +
+                       aReflowState.mComputedBorderPadding.LeftRight();
+  aDesiredSize.height = aReflowState.ComputedHeight() +
+                        aReflowState.mComputedBorderPadding.TopBottom();
+  aDesiredSize.height = NS_CSS_MINMAX(aDesiredSize.height,
+                                      aReflowState.mComputedMinHeight,
+                                      aReflowState.mComputedMaxHeight);
+
+  aDesiredSize.SetOverflowAreasToDesiredBounds();
+  ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
+  FinishAndStoreOverflow(&aDesiredSize);
+
+  aStatus = NS_FRAME_COMPLETE;
+
+  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
+
+  return NS_OK;
+}
+
+void
+nsMeterFrame::ReflowBarFrame(nsIFrame*                aBarFrame,
+                             nsPresContext*           aPresContext,
+                             const nsHTMLReflowState& aReflowState,
+                             nsReflowStatus&          aStatus)
+{
+  bool vertical = GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL;
+  nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame,
+                                nsSize(aReflowState.ComputedWidth(),
+                                       NS_UNCONSTRAINEDSIZE));
+  nscoord size = vertical ? aReflowState.ComputedHeight()
+                          : aReflowState.ComputedWidth();
+  nscoord xoffset = aReflowState.mComputedBorderPadding.left;
+  nscoord yoffset = aReflowState.mComputedBorderPadding.top;
+
+  // NOTE: Introduce a new function getPosition in the content part ?
+  double position, max, min, value;
+  nsCOMPtr<nsIDOMHTMLMeterElement> meterElement =
+    do_QueryInterface(mContent);
+
+  meterElement->GetMax(&max);
+  meterElement->GetMin(&min);
+  meterElement->GetValue(&value);
+
+  position = max - min;
+  position = position != 0 ? (value - min) / position : 1;
+
+  size = NSToCoordRound(size * position);
+
+  if (!vertical && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
+    xoffset += aReflowState.ComputedWidth() - size;
+  }
+
+  if (vertical) {
+    // We want the bar to begin at the bottom.
+    yoffset += aReflowState.ComputedHeight() - size;
+
+    size -= reflowState.mComputedMargin.TopBottom() +
+            reflowState.mComputedBorderPadding.TopBottom();
+    size = NS_MAX(size, 0);
+    reflowState.SetComputedHeight(size);
+  } else {
+    size -= reflowState.mComputedMargin.LeftRight() +
+            reflowState.mComputedBorderPadding.LeftRight();
+    size = NS_MAX(size, 0);
+    reflowState.SetComputedWidth(size);
+  }
+
+  xoffset += reflowState.mComputedMargin.left;
+  yoffset += reflowState.mComputedMargin.top;
+
+  nsHTMLReflowMetrics barDesiredSize;
+  ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset,
+              yoffset, 0, aStatus);
+  FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize,
+                    xoffset, yoffset, 0);
+}
+
+NS_IMETHODIMP
+nsMeterFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                               nsIAtom* aAttribute,
+                               PRInt32  aModType)
+{
+  NS_ASSERTION(mBarDiv, "Meter bar div must exist!");
+
+  if (aNameSpaceID == kNameSpaceID_None &&
+      (aAttribute == nsGkAtoms::value ||
+       aAttribute == nsGkAtoms::max   ||
+       aAttribute == nsGkAtoms::min )) {
+    nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
+    NS_ASSERTION(barFrame, "The meter frame should have a child with a frame!");
+    PresContext()->PresShell()->FrameNeedsReflow(barFrame,
+                                                 nsIPresShell::eResize,
+                                                 NS_FRAME_IS_DIRTY);
+  }
+
+  return nsContainerFrame::AttributeChanged(aNameSpaceID, aAttribute,
+                                            aModType);
+}
+
+nsSize
+nsMeterFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
+                              nsSize aCBSize, nscoord aAvailableWidth,
+                              nsSize aMargin, nsSize aBorder,
+                              nsSize aPadding, bool aShrinkWrap)
+{
+  nsRefPtr<nsFontMetrics> fontMet;
+  NS_ENSURE_SUCCESS(nsLayoutUtils::GetFontMetricsForFrame(this,
+                                                          getter_AddRefs(fontMet)),
+                    nsSize(0, 0));
+
+  nsSize autoSize;
+  autoSize.height = autoSize.width = fontMet->Font().size; // 1em
+
+  if (GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL) {
+    autoSize.height *= 5; // 5em
+  } else {
+    autoSize.width *= 5; // 5em
+  }
+  
+  return autoSize;
+}
new file mode 100644
--- /dev/null
+++ b/layout/forms/nsMeterFrame.h
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vincent Lamotte <Vincent.Lamotte@ensimag.imag.fr>
+ *   Laurent Dulary <Laurent.Dulary@ensimag.imag.fr>
+ *   Yoan Teboul <Yoan.Teboul@ensimag.imag.fr>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsMeterFrame_h___
+#define nsMeterFrame_h___
+
+#include "nsContainerFrame.h"
+#include "nsIAnonymousContentCreator.h"
+#include "nsCOMPtr.h"
+
+class nsMeterFrame : public nsContainerFrame,
+                     public nsIAnonymousContentCreator
+
+{
+public:
+  NS_DECL_QUERYFRAME_TARGET(nsMeterFrame)
+  NS_DECL_QUERYFRAME
+  NS_DECL_FRAMEARENA_HELPERS
+
+  nsMeterFrame(nsStyleContext* aContext);
+  virtual ~nsMeterFrame();
+
+  virtual void DestroyFrom(nsIFrame* aDestructRoot);
+
+  NS_IMETHOD Reflow(nsPresContext*           aCX,
+                    nsHTMLReflowMetrics&     aDesiredSize,
+                    const nsHTMLReflowState& aReflowState,
+                    nsReflowStatus&          aStatus);
+
+#ifdef NS_DEBUG
+  NS_IMETHOD GetFrameName(nsAString& aResult) const {
+    return MakeFrameName(NS_LITERAL_STRING("Meter"), aResult);
+  }
+#endif
+
+  virtual bool IsLeaf() const { return true; }
+
+  // nsIAnonymousContentCreator
+  virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements);
+  virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
+                                        PRUint32 aFilter);
+
+  NS_IMETHOD AttributeChanged(PRInt32  aNameSpaceID,
+                              nsIAtom* aAttribute,
+                              PRInt32  aModType);
+
+  virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
+                                 nsSize aCBSize, nscoord aAvailableWidth,
+                                 nsSize aMargin, nsSize aBorder,
+                                 nsSize aPadding, bool aShrinkWrap);
+
+  virtual bool IsFrameOfType(PRUint32 aFlags) const
+  {
+    return nsContainerFrame::IsFrameOfType(aFlags &
+      ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
+  }
+
+protected:
+  // Helper function which reflow the anonymous div frame.
+  void ReflowBarFrame(nsIFrame*                aBarFrame,
+                      nsPresContext*           aPresContext,
+                      const nsHTMLReflowState& aReflowState,
+                      nsReflowStatus&          aStatus);
+  /**
+   * The div used to show the meter bar.
+   * @see nsMeterFrame::CreateAnonymousContent
+   */
+  nsCOMPtr<nsIContent> mBarDiv;
+};
+
+#endif
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -182,16 +182,18 @@ NS_NewNativeRadioControlFrame(nsIPresShe
 nsIFrame*
 NS_NewNativeSelectControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
 nsIFrame*
 NS_NewProgressFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
+nsIFrame*
+NS_NewMeterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 
 // Table frame factories
 nsIFrame*
 NS_NewTableOuterFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
 nsIFrame*
 NS_NewTableCaptionFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
--- a/layout/generic/nsQueryFrame.h
+++ b/layout/generic/nsQueryFrame.h
@@ -136,16 +136,17 @@ public:
     nsMathMLmtrFrame_id,
     nsMathMLmunderFrame_id,
     nsMathMLmunderoverFrame_id,
     nsMathMLsemanticsFrame_id,
     nsMathMLTokenFrame_id,
     nsMenuBarFrame_id,
     nsMenuFrame_id,
     nsMenuPopupFrame_id,
+    nsMeterFrame_id,
     nsObjectFrame_id,
     nsPageBreakFrame_id,
     nsPageContentFrame_id,
     nsPageFrame_id,
     nsPlaceholderFrame_id,
     nsPopupSetFrame_id,
     nsProgressFrame_id,
     nsProgressMeterFrame_id,
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -661,16 +661,51 @@ progress {
   -moz-appearance: progresschunk;
   height: 100%;
   width: 100%;
 
   /* Default style in case of there is -moz-appearance: none; */
   background-color: #0064b4; /* blue */
 }
 
+meter {
+  /* Add a new moz-appearance : Bug 659999
+   * -moz-appearance: meterbar;
+   */
+  display: inline-block;
+  vertical-align: -0.2em;
+
+  /* Default style in case of there is -moz-appearance: none; */
+  border: 2px solid;
+  /* #e6e6e6 is a light gray. */
+  -moz-border-top-colors: ThreeDShadow #e6e6e6;
+  -moz-border-right-colors: ThreeDHighlight #e6e6e6;
+  -moz-border-bottom-colors: ThreeDHighlight #e6e6e6;
+  -moz-border-left-colors: ThreeDShadow #e6e6e6;
+  background-color: #e6e6e6;
+}
+
+::-moz-meter-bar {
+  display: inline-block ! important;
+  float: none ! important;
+  position: static ! important;
+  overflow: visible ! important;
+  /* Add a new moz-appearance : Bug 660232
+   * -moz-appearance: meterchunk;
+   */
+
+  height: 100%;
+  width: 100%;
+
+  /* Default style in case of there is -moz-appearance: none;
+   * #2eff46 is green
+   */
+  background-color: #2eff46;
+}
+
 %ifdef XP_OS2
 input {
   font: medium serif; font-family: inherit
 }
 
 select {
   font: medium serif; font-family: inherit
 }
--- a/layout/style/nsCSSPseudoElementList.h
+++ b/layout/style/nsCSSPseudoElementList.h
@@ -48,9 +48,10 @@ CSS_PSEUDO_ELEMENT(mozFocusOuter, ":-moz
 CSS_PSEUDO_ELEMENT(mozListBullet, ":-moz-list-bullet", 0)
 CSS_PSEUDO_ELEMENT(mozListNumber, ":-moz-list-number", 0)
 
 CSS_PSEUDO_ELEMENT(mozMathStretchy, ":-moz-math-stretchy", 0)
 CSS_PSEUDO_ELEMENT(mozMathAnonymous, ":-moz-math-anonymous", 0)
 
 // HTML5 Forms pseudo elements
 CSS_PSEUDO_ELEMENT(mozProgressBar, ":-moz-progress-bar", 0)
+CSS_PSEUDO_ELEMENT(mozMeterBar, ":-moz-meter-bar", 0)