LCOV - code coverage report
Current view: top level - layout/mathml - nsMathMLFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 154 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 18 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsMathMLFrame.h"
       7             : 
       8             : #include "gfxContext.h"
       9             : #include "gfxUtils.h"
      10             : #include "mozilla/gfx/2D.h"
      11             : #include "nsLayoutUtils.h"
      12             : #include "nsNameSpaceManager.h"
      13             : #include "nsMathMLChar.h"
      14             : #include "nsCSSPseudoElements.h"
      15             : #include "nsMathMLElement.h"
      16             : #include "gfxMathTable.h"
      17             : 
      18             : // used to map attributes into CSS rules
      19             : #include "mozilla/StyleSetHandle.h"
      20             : #include "mozilla/StyleSetHandleInlines.h"
      21             : #include "nsDisplayList.h"
      22             : 
      23             : using namespace mozilla;
      24             : using namespace mozilla::gfx;
      25             : 
      26             : eMathMLFrameType
      27           0 : nsMathMLFrame::GetMathMLFrameType()
      28             : {
      29             :   // see if it is an embellished operator (mapped to 'Op' in TeX)
      30           0 :   if (mEmbellishData.coreFrame)
      31           0 :     return GetMathMLFrameTypeFor(mEmbellishData.coreFrame);
      32             : 
      33             :   // if it has a prescribed base, fetch the type from there
      34           0 :   if (mPresentationData.baseFrame)
      35           0 :     return GetMathMLFrameTypeFor(mPresentationData.baseFrame);
      36             : 
      37             :   // everything else is treated as ordinary (mapped to 'Ord' in TeX)
      38           0 :   return eMathMLFrameType_Ordinary;
      39             : }
      40             : 
      41             : NS_IMETHODIMP
      42           0 : nsMathMLFrame::InheritAutomaticData(nsIFrame* aParent)
      43             : {
      44           0 :   mEmbellishData.flags = 0;
      45           0 :   mEmbellishData.coreFrame = nullptr;
      46           0 :   mEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
      47           0 :   mEmbellishData.leadingSpace = 0;
      48           0 :   mEmbellishData.trailingSpace = 0;
      49             : 
      50           0 :   mPresentationData.flags = 0;
      51           0 :   mPresentationData.baseFrame = nullptr;
      52             : 
      53             :   // by default, just inherit the display of our parent
      54           0 :   nsPresentationData parentData;
      55           0 :   GetPresentationDataFrom(aParent, parentData);
      56             : 
      57             : #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX)
      58             :   mPresentationData.flags |= NS_MATHML_SHOW_BOUNDING_METRICS;
      59             : #endif
      60             : 
      61           0 :   return NS_OK;
      62             : }
      63             : 
      64             : NS_IMETHODIMP
      65           0 : nsMathMLFrame::UpdatePresentationData(uint32_t        aFlagsValues,
      66             :                                       uint32_t        aWhichFlags)
      67             : {
      68           0 :   NS_ASSERTION(NS_MATHML_IS_COMPRESSED(aWhichFlags) ||
      69             :                NS_MATHML_IS_DTLS_SET(aWhichFlags),
      70             :                "aWhichFlags should only be compression or dtls flag");
      71             : 
      72           0 :   if (NS_MATHML_IS_COMPRESSED(aWhichFlags)) {
      73             :     // updating the compression flag is allowed
      74           0 :     if (NS_MATHML_IS_COMPRESSED(aFlagsValues)) {
      75             :       // 'compressed' means 'prime' style in App. G, TeXbook
      76           0 :       mPresentationData.flags |= NS_MATHML_COMPRESSED;
      77             :     }
      78             :     // no else. the flag is sticky. it retains its value once it is set
      79             :   }
      80             :   // These flags determine whether the dtls font feature settings should
      81             :   // be applied.
      82           0 :   if (NS_MATHML_IS_DTLS_SET(aWhichFlags)) {
      83           0 :     if (NS_MATHML_IS_DTLS_SET(aFlagsValues)) {
      84           0 :       mPresentationData.flags |= NS_MATHML_DTLS;
      85             :     } else {
      86           0 :       mPresentationData.flags &= ~NS_MATHML_DTLS;
      87             :     }
      88             :   }
      89           0 :   return NS_OK;
      90             : }
      91             : 
      92             : // Helper to give a style context suitable for doing the stretching of
      93             : // a MathMLChar. Frame classes that use this should ensure that the
      94             : // extra leaf style contexts given to the MathMLChars are accessible to
      95             : // the Style System via the Get/Set AdditionalStyleContext() APIs.
      96             : /* static */ void
      97           0 : nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext*  aPresContext,
      98             :                                       nsIContent*      aContent,
      99             :                                       nsStyleContext*  aParentStyleContext,
     100             :                                       nsMathMLChar*    aMathMLChar)
     101             : {
     102             :   CSSPseudoElementType pseudoType =
     103           0 :     CSSPseudoElementType::mozMathAnonymous; // savings
     104           0 :   RefPtr<nsStyleContext> newStyleContext;
     105           0 :   newStyleContext = aPresContext->StyleSet()->
     106           0 :     ResolvePseudoElementStyle(aContent->AsElement(), pseudoType,
     107           0 :                               aParentStyleContext, nullptr);
     108             : 
     109           0 :   aMathMLChar->SetStyleContext(newStyleContext);
     110           0 : }
     111             : 
     112             : /* static */ void
     113           0 : nsMathMLFrame::GetEmbellishDataFrom(nsIFrame*        aFrame,
     114             :                                     nsEmbellishData& aEmbellishData)
     115             : {
     116             :   // initialize OUT params
     117           0 :   aEmbellishData.flags = 0;
     118           0 :   aEmbellishData.coreFrame = nullptr;
     119           0 :   aEmbellishData.direction = NS_STRETCH_DIRECTION_UNSUPPORTED;
     120           0 :   aEmbellishData.leadingSpace = 0;
     121           0 :   aEmbellishData.trailingSpace = 0;
     122             : 
     123           0 :   if (aFrame && aFrame->IsFrameOfType(nsIFrame::eMathML)) {
     124           0 :     nsIMathMLFrame* mathMLFrame = do_QueryFrame(aFrame);
     125           0 :     if (mathMLFrame) {
     126           0 :       mathMLFrame->GetEmbellishData(aEmbellishData);
     127             :     }
     128             :   }
     129           0 : }
     130             : 
     131             : // helper to get the presentation data of a frame, by possibly walking up
     132             : // the frame hierarchy if we happen to be surrounded by non-MathML frames.
     133             : /* static */ void
     134           0 : nsMathMLFrame::GetPresentationDataFrom(nsIFrame*           aFrame,
     135             :                                        nsPresentationData& aPresentationData,
     136             :                                        bool                aClimbTree)
     137             : {
     138             :   // initialize OUT params
     139           0 :   aPresentationData.flags = 0;
     140           0 :   aPresentationData.baseFrame = nullptr;
     141             : 
     142           0 :   nsIFrame* frame = aFrame;
     143           0 :   while (frame) {
     144           0 :     if (frame->IsFrameOfType(nsIFrame::eMathML)) {
     145           0 :       nsIMathMLFrame* mathMLFrame = do_QueryFrame(frame);
     146           0 :       if (mathMLFrame) {
     147           0 :         mathMLFrame->GetPresentationData(aPresentationData);
     148           0 :         break;
     149             :       }
     150             :     }
     151             :     // stop if the caller doesn't want to lookup beyond the frame
     152           0 :     if (!aClimbTree) {
     153           0 :       break;
     154             :     }
     155             :     // stop if we reach the root <math> tag
     156           0 :     nsIContent* content = frame->GetContent();
     157           0 :     NS_ASSERTION(content || !frame->GetParent(), // no assert for the root
     158             :                  "dangling frame without a content node");
     159           0 :     if (!content)
     160           0 :       break;
     161             : 
     162           0 :     if (content->IsMathMLElement(nsGkAtoms::math)) {
     163           0 :       break;
     164             :     }
     165           0 :     frame = frame->GetParent();
     166             :   }
     167           0 :   NS_WARNING_ASSERTION(
     168             :     frame && frame->GetContent(),
     169             :     "bad MathML markup - could not find the top <math> element");
     170           0 : }
     171             : 
     172             : /* static */ void
     173           0 : nsMathMLFrame::GetRuleThickness(DrawTarget*    aDrawTarget,
     174             :                                 nsFontMetrics* aFontMetrics,
     175             :                                 nscoord&       aRuleThickness)
     176             : {
     177           0 :   nscoord xHeight = aFontMetrics->XHeight();
     178           0 :   char16_t overBar = 0x00AF;
     179             :   nsBoundingMetrics bm =
     180             :     nsLayoutUtils::AppUnitBoundsOfString(&overBar, 1, *aFontMetrics,
     181           0 :                                          aDrawTarget);
     182           0 :   aRuleThickness = bm.ascent + bm.descent;
     183           0 :   if (aRuleThickness <= 0 || aRuleThickness >= xHeight) {
     184             :     // fall-back to the other version
     185           0 :     GetRuleThickness(aFontMetrics, aRuleThickness);
     186             :   }
     187           0 : }
     188             : 
     189             : /* static */ void
     190           0 : nsMathMLFrame::GetAxisHeight(DrawTarget*    aDrawTarget,
     191             :                              nsFontMetrics* aFontMetrics,
     192             :                              nscoord&       aAxisHeight)
     193             : {
     194           0 :   gfxFont* mathFont = aFontMetrics->GetThebesFontGroup()->GetFirstMathFont();
     195           0 :   if (mathFont) {
     196           0 :     aAxisHeight =
     197           0 :       mathFont->MathTable()->Constant(gfxMathTable::AxisHeight,
     198           0 :                                       aFontMetrics->AppUnitsPerDevPixel());
     199           0 :     return;
     200             :   }
     201             : 
     202           0 :   nscoord xHeight = aFontMetrics->XHeight();
     203           0 :   char16_t minus = 0x2212; // not '-', but official Unicode minus sign
     204             :   nsBoundingMetrics bm =
     205           0 :     nsLayoutUtils::AppUnitBoundsOfString(&minus, 1, *aFontMetrics, aDrawTarget);
     206           0 :   aAxisHeight = bm.ascent - (bm.ascent + bm.descent)/2;
     207           0 :   if (aAxisHeight <= 0 || aAxisHeight >= xHeight) {
     208             :     // fall-back to the other version
     209           0 :     GetAxisHeight(aFontMetrics, aAxisHeight);
     210             :   }
     211             : }
     212             : 
     213             : /* static */ nscoord
     214           0 : nsMathMLFrame::CalcLength(nsPresContext*   aPresContext,
     215             :                           nsStyleContext*   aStyleContext,
     216             :                           const nsCSSValue& aCSSValue,
     217             :                           float             aFontSizeInflation)
     218             : {
     219           0 :   NS_ASSERTION(aCSSValue.IsLengthUnit(), "not a length unit");
     220             : 
     221           0 :   if (aCSSValue.IsFixedLengthUnit()) {
     222           0 :     return aCSSValue.GetFixedLength(aPresContext);
     223             :   }
     224           0 :   if (aCSSValue.IsPixelLengthUnit()) {
     225           0 :     return aCSSValue.GetPixelLength();
     226             :   }
     227             : 
     228           0 :   nsCSSUnit unit = aCSSValue.GetUnit();
     229             : 
     230           0 :   if (eCSSUnit_EM == unit) {
     231           0 :     const nsStyleFont* font = aStyleContext->StyleFont();
     232           0 :     return NSToCoordRound(aCSSValue.GetFloatValue() * (float)font->mFont.size);
     233             :   }
     234           0 :   else if (eCSSUnit_XHeight == unit) {
     235           0 :     aPresContext->SetUsesExChUnits(true);
     236             :     RefPtr<nsFontMetrics> fm = nsLayoutUtils::
     237           0 :       GetFontMetricsForStyleContext(aStyleContext, aFontSizeInflation);
     238           0 :     nscoord xHeight = fm->XHeight();
     239           0 :     return NSToCoordRound(aCSSValue.GetFloatValue() * (float)xHeight);
     240             :   }
     241             : 
     242             :   // MathML doesn't specify other CSS units such as rem or ch
     243           0 :   NS_ERROR("Unsupported unit");
     244           0 :   return 0;
     245             : }
     246             : 
     247             : /* static */ void
     248           0 : nsMathMLFrame::ParseNumericValue(const nsString&   aString,
     249             :                                  nscoord*          aLengthValue,
     250             :                                  uint32_t          aFlags,
     251             :                                  nsPresContext*    aPresContext,
     252             :                                  nsStyleContext*   aStyleContext,
     253             :                                  float             aFontSizeInflation)
     254             : {
     255           0 :   nsCSSValue cssValue;
     256             : 
     257           0 :   if (!nsMathMLElement::ParseNumericValue(aString, cssValue, aFlags,
     258             :                                           aPresContext->Document())) {
     259             :     // Invalid attribute value. aLengthValue remains unchanged, so the default
     260             :     // length value is used.
     261           0 :     return;
     262             :   }
     263             : 
     264           0 :   nsCSSUnit unit = cssValue.GetUnit();
     265             : 
     266           0 :   if (unit == eCSSUnit_Percent || unit == eCSSUnit_Number) {
     267             :     // Relative units. A multiple of the default length value is used.
     268           0 :     *aLengthValue = NSToCoordRound(*aLengthValue * (unit == eCSSUnit_Percent ?
     269             :                                                     cssValue.GetPercentValue() :
     270             :                                                     cssValue.GetFloatValue()));
     271           0 :     return;
     272             :   }
     273             : 
     274             :   // Absolute units.
     275           0 :   *aLengthValue = CalcLength(aPresContext, aStyleContext, cssValue,
     276             :                              aFontSizeInflation);
     277             : }
     278             : 
     279             : #if defined(DEBUG) && defined(SHOW_BOUNDING_BOX)
     280             : class nsDisplayMathMLBoundingMetrics : public nsDisplayItem {
     281             : public:
     282             :   nsDisplayMathMLBoundingMetrics(nsDisplayListBuilder* aBuilder,
     283             :                                  nsIFrame* aFrame, const nsRect& aRect)
     284             :     : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
     285             :     MOZ_COUNT_CTOR(nsDisplayMathMLBoundingMetrics);
     286             :   }
     287             : #ifdef NS_BUILD_REFCNT_LOGGING
     288             :   virtual ~nsDisplayMathMLBoundingMetrics() {
     289             :     MOZ_COUNT_DTOR(nsDisplayMathMLBoundingMetrics);
     290             :   }
     291             : #endif
     292             : 
     293             :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     294             :                      gfxContext* aCtx) override;
     295             :   NS_DISPLAY_DECL_NAME("MathMLBoundingMetrics", TYPE_MATHML_BOUNDING_METRICS)
     296             : private:
     297             :   nsRect    mRect;
     298             : };
     299             : 
     300             : void nsDisplayMathMLBoundingMetrics::Paint(nsDisplayListBuilder* aBuilder,
     301             :                                            gfxContext* aCtx)
     302             : {
     303             :   DrawTarget* drawTarget = aCtx->GetDrawTarget();
     304             :   Rect r = NSRectToRect(mRect + ToReferenceFrame(),
     305             :                         mFrame->PresContext()->AppUnitsPerDevPixel());
     306             :   ColorPattern blue(ToDeviceColor(Color(0.f, 0.f, 1.f, 1.f)));
     307             :   drawTarget->StrokeRect(r, blue);
     308             : }
     309             : 
     310             : void
     311             : nsMathMLFrame::DisplayBoundingMetrics(nsDisplayListBuilder* aBuilder,
     312             :                                       nsIFrame* aFrame, const nsPoint& aPt,
     313             :                                       const nsBoundingMetrics& aMetrics,
     314             :                                       const nsDisplayListSet& aLists) {
     315             :   if (!NS_MATHML_PAINT_BOUNDING_METRICS(mPresentationData.flags))
     316             :     return;
     317             : 
     318             :   nscoord x = aPt.x + aMetrics.leftBearing;
     319             :   nscoord y = aPt.y - aMetrics.ascent;
     320             :   nscoord w = aMetrics.rightBearing - aMetrics.leftBearing;
     321             :   nscoord h = aMetrics.ascent + aMetrics.descent;
     322             : 
     323             :   aLists.Content()->AppendNewToTop(new (aBuilder)
     324             :       nsDisplayMathMLBoundingMetrics(aBuilder, aFrame, nsRect(x,y,w,h)));
     325             : }
     326             : #endif
     327             : 
     328             : class nsDisplayMathMLBar : public nsDisplayItem {
     329             : public:
     330           0 :   nsDisplayMathMLBar(nsDisplayListBuilder* aBuilder,
     331             :                      nsIFrame* aFrame, const nsRect& aRect)
     332           0 :     : nsDisplayItem(aBuilder, aFrame), mRect(aRect) {
     333           0 :     MOZ_COUNT_CTOR(nsDisplayMathMLBar);
     334           0 :   }
     335             : #ifdef NS_BUILD_REFCNT_LOGGING
     336           0 :   virtual ~nsDisplayMathMLBar() {
     337           0 :     MOZ_COUNT_DTOR(nsDisplayMathMLBar);
     338           0 :   }
     339             : #endif
     340             : 
     341             :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     342             :                      gfxContext* aCtx) override;
     343           0 :   NS_DISPLAY_DECL_NAME("MathMLBar", TYPE_MATHML_BAR)
     344             : private:
     345             :   nsRect    mRect;
     346             : };
     347             : 
     348           0 : void nsDisplayMathMLBar::Paint(nsDisplayListBuilder* aBuilder,
     349             :                                gfxContext* aCtx)
     350             : {
     351             :   // paint the bar with the current text color
     352           0 :   DrawTarget* drawTarget = aCtx->GetDrawTarget();
     353             :   Rect rect =
     354           0 :     NSRectToNonEmptySnappedRect(mRect + ToReferenceFrame(),
     355           0 :                                 mFrame->PresContext()->AppUnitsPerDevPixel(),
     356           0 :                                 *drawTarget);
     357           0 :   ColorPattern color(ToDeviceColor(
     358           0 :     mFrame->GetVisitedDependentColor(&nsStyleText::mWebkitTextFillColor)));
     359           0 :   drawTarget->FillRect(rect, color);
     360           0 : }
     361             : 
     362             : void
     363           0 : nsMathMLFrame::DisplayBar(nsDisplayListBuilder* aBuilder,
     364             :                           nsIFrame* aFrame, const nsRect& aRect,
     365             :                           const nsDisplayListSet& aLists) {
     366           0 :   if (!aFrame->StyleVisibility()->IsVisible() || aRect.IsEmpty())
     367           0 :     return;
     368             : 
     369           0 :   aLists.Content()->AppendNewToTop(new (aBuilder)
     370           0 :     nsDisplayMathMLBar(aBuilder, aFrame, aRect));
     371             : }
     372             : 
     373             : void
     374           0 : nsMathMLFrame::GetRadicalParameters(nsFontMetrics* aFontMetrics,
     375             :                                     bool aDisplayStyle,
     376             :                                     nscoord& aRadicalRuleThickness,
     377             :                                     nscoord& aRadicalExtraAscender,
     378             :                                     nscoord& aRadicalVerticalGap)
     379             : {
     380           0 :   nscoord oneDevPixel = aFontMetrics->AppUnitsPerDevPixel();
     381           0 :   gfxFont* mathFont = aFontMetrics->GetThebesFontGroup()->GetFirstMathFont();
     382             : 
     383             :   // get the radical rulethickness
     384           0 :   if (mathFont) {
     385           0 :     aRadicalRuleThickness = mathFont->MathTable()->
     386           0 :       Constant(gfxMathTable::RadicalRuleThickness, oneDevPixel);
     387             :   } else {
     388           0 :     GetRuleThickness(aFontMetrics, aRadicalRuleThickness);
     389             :   }
     390             : 
     391             :   // get the leading to be left at the top of the resulting frame
     392           0 :   if (mathFont) {
     393           0 :     aRadicalExtraAscender = mathFont->MathTable()->
     394           0 :       Constant(gfxMathTable::RadicalExtraAscender, oneDevPixel);
     395             :   } else {
     396             :     // This seems more reliable than using aFontMetrics->GetLeading() on
     397             :     // suspicious fonts.
     398             :     nscoord em;
     399           0 :     GetEmHeight(aFontMetrics, em);
     400           0 :     aRadicalExtraAscender = nscoord(0.2f * em);
     401             :   }
     402             : 
     403             :   // get the clearance between rule and content
     404           0 :   if (mathFont) {
     405           0 :     aRadicalVerticalGap = mathFont->MathTable()->
     406           0 :       Constant(aDisplayStyle ?
     407             :                gfxMathTable::RadicalDisplayStyleVerticalGap :
     408             :                gfxMathTable::RadicalVerticalGap,
     409             :                oneDevPixel);
     410             :   } else {
     411             :     // Rule 11, App. G, TeXbook
     412           0 :     aRadicalVerticalGap = aRadicalRuleThickness +
     413           0 :       (aDisplayStyle ? aFontMetrics->XHeight() : aRadicalRuleThickness) / 4;
     414             :   }
     415           0 : }

Generated by: LCOV version 1.13