WebCore/mathml/RenderMathMLFraction.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved.
       
     3  * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved.
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  * 1. Redistributions of source code must retain the above copyright
       
     9  *    notice, this list of conditions and the following disclaimer.
       
    10  * 2. Redistributions in binary form must reproduce the above copyright
       
    11  *    notice, this list of conditions and the following disclaimer in the
       
    12  *    documentation and/or other materials provided with the distribution.
       
    13  *
       
    14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    25  */
       
    26 
       
    27 #include "config.h"
       
    28 
       
    29 #if ENABLE(MATHML)
       
    30 
       
    31 #include "RenderMathMLFraction.h"
       
    32 
       
    33 #include "GraphicsContext.h"
       
    34 #include "MathMLNames.h"
       
    35 #include "RenderText.h"
       
    36 
       
    37 namespace WebCore {
       
    38     
       
    39 using namespace MathMLNames;
       
    40 
       
    41 static const double gHorizontalPad = 0.2;
       
    42 static const int gLineThin = 1;
       
    43 static const int gLineMedium = 3;
       
    44 static const int gLineThick = 5;
       
    45 static const double gFractionAlignment = 0.25;
       
    46 static const double gFractionBarWidth = 0.05;
       
    47 static const double gDenominatorPad = 0.1;
       
    48 
       
    49 RenderMathMLFraction::RenderMathMLFraction(Element* fraction) 
       
    50     : RenderMathMLBlock(fraction)
       
    51     , m_lineThickness(gLineThin)
       
    52 {
       
    53     setChildrenInline(false);
       
    54 }
       
    55 
       
    56 void RenderMathMLFraction::updateFromElement()
       
    57 {
       
    58     // FIXME: mfrac where bevelled=true will need to reorganize the descendants
       
    59     if (isEmpty()) 
       
    60         return;
       
    61     
       
    62     Element* fraction = static_cast<Element*>(node());
       
    63     
       
    64     RenderObject* numerator = firstChild();
       
    65     String nalign = fraction->getAttribute(MathMLNames::numalignAttr);
       
    66     if (equalIgnoringCase(nalign, "left"))
       
    67         numerator->style()->setTextAlign(LEFT);
       
    68     else if (equalIgnoringCase(nalign, "right"))
       
    69         numerator->style()->setTextAlign(RIGHT);
       
    70     else
       
    71         numerator->style()->setTextAlign(CENTER);
       
    72     
       
    73     RenderObject* denominator = numerator->nextSibling();
       
    74     if (!denominator)
       
    75         return;
       
    76     
       
    77     String dalign = fraction->getAttribute(MathMLNames::denomalignAttr);
       
    78     if (equalIgnoringCase(dalign, "left"))
       
    79         denominator->style()->setTextAlign(LEFT);
       
    80     else if (equalIgnoringCase(dalign, "right"))
       
    81         denominator->style()->setTextAlign(RIGHT);
       
    82     else
       
    83         denominator->style()->setTextAlign(CENTER);
       
    84     
       
    85     // FIXME: parse units
       
    86     String thickness = fraction->getAttribute(MathMLNames::linethicknessAttr);
       
    87     m_lineThickness = gLineThin;
       
    88     if (equalIgnoringCase(thickness, "thin"))
       
    89         m_lineThickness = gLineThin;
       
    90     else if (equalIgnoringCase(thickness, "medium"))
       
    91         m_lineThickness = gLineMedium;
       
    92     else if (equalIgnoringCase(thickness, "thick"))
       
    93         m_lineThickness = gLineThick;
       
    94     else if (equalIgnoringCase(thickness, "0"))
       
    95         m_lineThickness = 0;
       
    96 
       
    97     // Update the style for the padding of the denominator for the line thickness
       
    98     lastChild()->style()->setPaddingTop(Length(static_cast<int>(m_lineThickness + style()->fontSize() * gDenominatorPad), Fixed));
       
    99 }
       
   100 
       
   101 void RenderMathMLFraction::addChild(RenderObject* child, RenderObject* beforeChild)
       
   102 {
       
   103     RenderBlock* row = new (renderArena()) RenderMathMLBlock(node());
       
   104     RefPtr<RenderStyle> rowStyle = makeBlockStyle();
       
   105     
       
   106     rowStyle->setTextAlign(CENTER);
       
   107     Length pad(static_cast<int>(rowStyle->fontSize() * gHorizontalPad), Fixed);
       
   108     rowStyle->setPaddingLeft(pad);
       
   109     rowStyle->setPaddingRight(pad);
       
   110     
       
   111     // Only add padding for rows as denominators
       
   112     bool isNumerator = isEmpty();
       
   113     if (!isNumerator) 
       
   114         rowStyle->setPaddingTop(Length(2, Fixed));
       
   115     
       
   116     row->setStyle(rowStyle.release());
       
   117     RenderBlock::addChild(row, beforeChild);
       
   118     row->addChild(child);
       
   119     updateFromElement();
       
   120 }
       
   121 
       
   122 void RenderMathMLFraction::layout()
       
   123 {
       
   124     updateFromElement();
       
   125     
       
   126     // Adjust the fraction line thickness for the zoom
       
   127     if (lastChild() && lastChild()->isRenderBlock())
       
   128         m_lineThickness = m_lineThickness * ceil(gFractionBarWidth * style()->fontSize());
       
   129     
       
   130     RenderBlock::layout();
       
   131     
       
   132     // The row layout can affect the numerator/denominator width.
       
   133     // FIXME: This is probably only needed if one of the children
       
   134     // contains an mrow.
       
   135     setNeedsLayoutAndPrefWidthsRecalc();
       
   136     markContainingBlocksForLayout();
       
   137     
       
   138     RenderBlock::layout();
       
   139     
       
   140 }
       
   141     
       
   142 void RenderMathMLFraction::paint(PaintInfo& info, int tx, int ty)
       
   143 {
       
   144     RenderMathMLBlock::paint(info, tx, ty);
       
   145     if (info.context->paintingDisabled() || info.phase != PaintPhaseForeground)
       
   146         return;
       
   147     
       
   148     if (!firstChild() ||!m_lineThickness)
       
   149         return;
       
   150 
       
   151     int verticalOffset = 0;
       
   152     // The children are always RenderMathMLBlock instances
       
   153     if (firstChild()->isRenderMathMLBlock()) {
       
   154         int adjustForThickness = m_lineThickness > 1 ? m_lineThickness / 2 : 1;
       
   155         if (m_lineThickness % 2 == 1)
       
   156             adjustForThickness++;
       
   157         RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
       
   158         if (numerator->isRenderMathMLRow())
       
   159             verticalOffset = numerator->offsetHeight() + adjustForThickness;
       
   160         else 
       
   161             verticalOffset = numerator->offsetHeight();        
       
   162     }
       
   163     
       
   164     tx += x();
       
   165     ty += y() + verticalOffset;
       
   166     
       
   167     info.context->save();
       
   168     
       
   169     info.context->setStrokeThickness(static_cast<float>(m_lineThickness));
       
   170     info.context->setStrokeStyle(SolidStroke);
       
   171     info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), sRGBColorSpace);
       
   172     
       
   173     info.context->drawLine(IntPoint(tx, ty), IntPoint(tx + offsetWidth(), ty));
       
   174     
       
   175     info.context->restore();
       
   176 }
       
   177 
       
   178 int RenderMathMLFraction::baselinePosition(bool firstLine, bool isRootLineBox) const
       
   179 {
       
   180     if (firstChild()->isRenderMathMLBlock()) {
       
   181         RenderMathMLBlock* numerator = toRenderMathMLBlock(firstChild());
       
   182         // FIXME: the baseline should adjust so the fraction line aligns
       
   183         // relative certain operators (e.g. aligns with the horizontal
       
   184         // stroke of the plus).  1/3 of the current font size is just
       
   185         // a good guess.
       
   186         return numerator->offsetHeight() + style()->fontSize() / 3;
       
   187     }
       
   188     return RenderBlock::baselinePosition(firstLine, isRootLineBox);
       
   189 }
       
   190 
       
   191 }
       
   192 
       
   193 
       
   194 #endif // ENABLE(MATHML)