121939df44de1705786c545cd1bf519d47250322dBen Murdoch/* 221939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2009 Alex Milowski (alex@milowski.com). All rights reserved. 321939df44de1705786c545cd1bf519d47250322dBen Murdoch * Copyright (C) 2010 François Sausset (sausset@gmail.com). All rights reserved. 421939df44de1705786c545cd1bf519d47250322dBen Murdoch * 521939df44de1705786c545cd1bf519d47250322dBen Murdoch * Redistribution and use in source and binary forms, with or without 621939df44de1705786c545cd1bf519d47250322dBen Murdoch * modification, are permitted provided that the following conditions 721939df44de1705786c545cd1bf519d47250322dBen Murdoch * are met: 821939df44de1705786c545cd1bf519d47250322dBen Murdoch * 1. Redistributions of source code must retain the above copyright 921939df44de1705786c545cd1bf519d47250322dBen Murdoch * notice, this list of conditions and the following disclaimer. 1021939df44de1705786c545cd1bf519d47250322dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright 1121939df44de1705786c545cd1bf519d47250322dBen Murdoch * notice, this list of conditions and the following disclaimer in the 1221939df44de1705786c545cd1bf519d47250322dBen Murdoch * documentation and/or other materials provided with the distribution. 1321939df44de1705786c545cd1bf519d47250322dBen Murdoch * 1421939df44de1705786c545cd1bf519d47250322dBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1521939df44de1705786c545cd1bf519d47250322dBen Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1621939df44de1705786c545cd1bf519d47250322dBen Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1721939df44de1705786c545cd1bf519d47250322dBen Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1821939df44de1705786c545cd1bf519d47250322dBen Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1921939df44de1705786c545cd1bf519d47250322dBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2021939df44de1705786c545cd1bf519d47250322dBen Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2121939df44de1705786c545cd1bf519d47250322dBen Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2221939df44de1705786c545cd1bf519d47250322dBen Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2321939df44de1705786c545cd1bf519d47250322dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2421939df44de1705786c545cd1bf519d47250322dBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2521939df44de1705786c545cd1bf519d47250322dBen Murdoch */ 2621939df44de1705786c545cd1bf519d47250322dBen Murdoch 2721939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "config.h" 2821939df44de1705786c545cd1bf519d47250322dBen Murdoch 2921939df44de1705786c545cd1bf519d47250322dBen Murdoch#if ENABLE(MATHML) 3021939df44de1705786c545cd1bf519d47250322dBen Murdoch 3121939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "RenderMathMLSquareRoot.h" 3221939df44de1705786c545cd1bf519d47250322dBen Murdoch 3321939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "GraphicsContext.h" 3421939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "MathMLNames.h" 3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "PaintInfo.h" 3621939df44de1705786c545cd1bf519d47250322dBen Murdoch#include "Path.h" 3721939df44de1705786c545cd1bf519d47250322dBen Murdoch 3821939df44de1705786c545cd1bf519d47250322dBen Murdochnamespace WebCore { 3921939df44de1705786c545cd1bf519d47250322dBen Murdoch 4021939df44de1705786c545cd1bf519d47250322dBen Murdochusing namespace MathMLNames; 4121939df44de1705786c545cd1bf519d47250322dBen Murdoch 4221939df44de1705786c545cd1bf519d47250322dBen Murdoch// Bottom padding of the radical (px) 4321939df44de1705786c545cd1bf519d47250322dBen Murdochconst int gRadicalBasePad = 3; 4421939df44de1705786c545cd1bf519d47250322dBen Murdoch// Threshold above which the radical shape is modified to look nice with big bases (%) 45dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gThresholdBaseHeight = 1.5f; 4621939df44de1705786c545cd1bf519d47250322dBen Murdoch// Radical width (%) 47dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalWidth = 0.75f; 4821939df44de1705786c545cd1bf519d47250322dBen Murdoch// Horizontal position of the bottom point of the radical (%) 49dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalBottomPointXPos= 0.5f; 5021939df44de1705786c545cd1bf519d47250322dBen Murdoch// Horizontal position of the top left point of the radical (%) 51dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalTopLeftPointXPos = 0.2f; 5221939df44de1705786c545cd1bf519d47250322dBen Murdoch// Vertical position of the top left point of the radical (%) 53dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalTopLeftPointYPos = 0.5f; 5421939df44de1705786c545cd1bf519d47250322dBen Murdoch// Vertical shift of the left end point of the radical (%) 55dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalLeftEndYShift = 0.05f; 5621939df44de1705786c545cd1bf519d47250322dBen Murdoch// Additional bottom root padding (%) 57dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRootBottomPadding = 0.2f; 5821939df44de1705786c545cd1bf519d47250322dBen Murdoch 5921939df44de1705786c545cd1bf519d47250322dBen Murdoch// Radical line thickness (%) 60dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalLineThickness = 0.02f; 6121939df44de1705786c545cd1bf519d47250322dBen Murdoch// Radical thick line thickness (%) 62dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdochconst float gRadicalThickLineThickness = 0.1f; 6321939df44de1705786c545cd1bf519d47250322dBen Murdoch 6421939df44de1705786c545cd1bf519d47250322dBen MurdochRenderMathMLSquareRoot::RenderMathMLSquareRoot(Node *expression) 6521939df44de1705786c545cd1bf519d47250322dBen Murdoch : RenderMathMLBlock(expression) 6621939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 6721939df44de1705786c545cd1bf519d47250322dBen Murdoch} 6821939df44de1705786c545cd1bf519d47250322dBen Murdoch 6921939df44de1705786c545cd1bf519d47250322dBen Murdochvoid RenderMathMLSquareRoot::paint(PaintInfo& info, int tx, int ty) 7021939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 7121939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderMathMLBlock::paint(info, tx, ty); 7221939df44de1705786c545cd1bf519d47250322dBen Murdoch 7306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen if (info.context->paintingDisabled()) 7406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen return; 7506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 7621939df44de1705786c545cd1bf519d47250322dBen Murdoch tx += x(); 7721939df44de1705786c545cd1bf519d47250322dBen Murdoch ty += y(); 7821939df44de1705786c545cd1bf519d47250322dBen Murdoch 7921939df44de1705786c545cd1bf519d47250322dBen Murdoch int maxHeight = 0; 8021939df44de1705786c545cd1bf519d47250322dBen Murdoch int width = 0; 8121939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderObject* current = firstChild(); 8221939df44de1705786c545cd1bf519d47250322dBen Murdoch while (current) { 8321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (current->isBoxModelObject()) { 8421939df44de1705786c545cd1bf519d47250322dBen Murdoch 8521939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderBoxModelObject* box = toRenderBoxModelObject(current); 8621939df44de1705786c545cd1bf519d47250322dBen Murdoch 8721939df44de1705786c545cd1bf519d47250322dBen Murdoch // Check to see if this box has a larger height 8821939df44de1705786c545cd1bf519d47250322dBen Murdoch if (box->offsetHeight() > maxHeight) 8921939df44de1705786c545cd1bf519d47250322dBen Murdoch maxHeight = box->offsetHeight(); 9021939df44de1705786c545cd1bf519d47250322dBen Murdoch width += box->offsetWidth(); 9121939df44de1705786c545cd1bf519d47250322dBen Murdoch } 9221939df44de1705786c545cd1bf519d47250322dBen Murdoch current = current->nextSibling(); 9321939df44de1705786c545cd1bf519d47250322dBen Murdoch } 9421939df44de1705786c545cd1bf519d47250322dBen Murdoch // default to the font size in pixels if we're empty 9521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!maxHeight) 9621939df44de1705786c545cd1bf519d47250322dBen Murdoch maxHeight = style()->fontSize(); 9721939df44de1705786c545cd1bf519d47250322dBen Murdoch 9821939df44de1705786c545cd1bf519d47250322dBen Murdoch int frontWidth = static_cast<int>(style()->fontSize() * gRadicalWidth); 9921939df44de1705786c545cd1bf519d47250322dBen Murdoch int topStartShift = 0; 10021939df44de1705786c545cd1bf519d47250322dBen Murdoch // Base height above which the shape of the root changes 10121939df44de1705786c545cd1bf519d47250322dBen Murdoch int thresholdHeight = static_cast<int>(gThresholdBaseHeight * style()->fontSize()); 10221939df44de1705786c545cd1bf519d47250322dBen Murdoch 10321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (maxHeight > thresholdHeight && thresholdHeight) { 10421939df44de1705786c545cd1bf519d47250322dBen Murdoch float shift = (maxHeight - thresholdHeight) / static_cast<float>(thresholdHeight); 10521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (shift > 1.) 106dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch shift = 1.0f; 10721939df44de1705786c545cd1bf519d47250322dBen Murdoch topStartShift = static_cast<int>(gRadicalBottomPointXPos * frontWidth * shift); 10821939df44de1705786c545cd1bf519d47250322dBen Murdoch } 10921939df44de1705786c545cd1bf519d47250322dBen Murdoch 11021939df44de1705786c545cd1bf519d47250322dBen Murdoch width += topStartShift; 11121939df44de1705786c545cd1bf519d47250322dBen Murdoch 11221939df44de1705786c545cd1bf519d47250322dBen Murdoch FloatPoint topStart(tx + frontWidth - topStartShift, ty); 11321939df44de1705786c545cd1bf519d47250322dBen Murdoch FloatPoint bottomLeft(tx + frontWidth * gRadicalBottomPointXPos , ty + maxHeight + gRadicalBasePad); 11421939df44de1705786c545cd1bf519d47250322dBen Murdoch FloatPoint topLeft(tx + frontWidth * gRadicalTopLeftPointXPos , ty + gRadicalTopLeftPointYPos * maxHeight); 11521939df44de1705786c545cd1bf519d47250322dBen Murdoch FloatPoint leftEnd(tx , topLeft.y() + gRadicalLeftEndYShift * style()->fontSize()); 11621939df44de1705786c545cd1bf519d47250322dBen Murdoch 11721939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->save(); 11821939df44de1705786c545cd1bf519d47250322dBen Murdoch 11921939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setStrokeThickness(gRadicalLineThickness * style()->fontSize()); 12021939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setStrokeStyle(SolidStroke); 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch info.context->setStrokeColor(style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); 12221939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setLineJoin(MiterJoin); 12321939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setMiterLimit(style()->fontSize()); 12421939df44de1705786c545cd1bf519d47250322dBen Murdoch 12521939df44de1705786c545cd1bf519d47250322dBen Murdoch Path root; 12621939df44de1705786c545cd1bf519d47250322dBen Murdoch 12721939df44de1705786c545cd1bf519d47250322dBen Murdoch root.moveTo(FloatPoint(topStart.x() + width , ty)); 12821939df44de1705786c545cd1bf519d47250322dBen Murdoch // draw top 12921939df44de1705786c545cd1bf519d47250322dBen Murdoch root.addLineTo(topStart); 13021939df44de1705786c545cd1bf519d47250322dBen Murdoch // draw from top left corner to bottom point of radical 13121939df44de1705786c545cd1bf519d47250322dBen Murdoch root.addLineTo(bottomLeft); 13221939df44de1705786c545cd1bf519d47250322dBen Murdoch // draw from bottom point to top of left part of radical base "pocket" 13321939df44de1705786c545cd1bf519d47250322dBen Murdoch root.addLineTo(topLeft); 13421939df44de1705786c545cd1bf519d47250322dBen Murdoch // draw to end 13521939df44de1705786c545cd1bf519d47250322dBen Murdoch root.addLineTo(leftEnd); 136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch info.context->strokePath(root); 13821939df44de1705786c545cd1bf519d47250322dBen Murdoch 13921939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->save(); 14021939df44de1705786c545cd1bf519d47250322dBen Murdoch 14121939df44de1705786c545cd1bf519d47250322dBen Murdoch // Build a mask to draw the thick part of the root. 14221939df44de1705786c545cd1bf519d47250322dBen Murdoch Path mask; 14321939df44de1705786c545cd1bf519d47250322dBen Murdoch 14421939df44de1705786c545cd1bf519d47250322dBen Murdoch mask.moveTo(topStart); 14521939df44de1705786c545cd1bf519d47250322dBen Murdoch mask.addLineTo(bottomLeft); 14621939df44de1705786c545cd1bf519d47250322dBen Murdoch mask.addLineTo(topLeft); 14721939df44de1705786c545cd1bf519d47250322dBen Murdoch mask.addLineTo(FloatPoint(2 * topLeft.x() - leftEnd.x(), 2 * topLeft.y() - leftEnd.y())); 14821939df44de1705786c545cd1bf519d47250322dBen Murdoch 14921939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->clip(mask); 15021939df44de1705786c545cd1bf519d47250322dBen Murdoch 15121939df44de1705786c545cd1bf519d47250322dBen Murdoch // Draw the thick part of the root. 15221939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setStrokeThickness(gRadicalThickLineThickness * style()->fontSize()); 15321939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->setLineCap(SquareCap); 15421939df44de1705786c545cd1bf519d47250322dBen Murdoch 15521939df44de1705786c545cd1bf519d47250322dBen Murdoch Path line; 156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch line.moveTo(bottomLeft); 157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch line.addLineTo(topLeft); 15821939df44de1705786c545cd1bf519d47250322dBen Murdoch 159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch info.context->strokePath(line); 16021939df44de1705786c545cd1bf519d47250322dBen Murdoch 16121939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->restore(); 16221939df44de1705786c545cd1bf519d47250322dBen Murdoch 16321939df44de1705786c545cd1bf519d47250322dBen Murdoch info.context->restore(); 16421939df44de1705786c545cd1bf519d47250322dBen Murdoch} 16521939df44de1705786c545cd1bf519d47250322dBen Murdoch 16621939df44de1705786c545cd1bf519d47250322dBen Murdochvoid RenderMathMLSquareRoot::layout() 16721939df44de1705786c545cd1bf519d47250322dBen Murdoch{ 16821939df44de1705786c545cd1bf519d47250322dBen Murdoch int maxHeight = 0; 16921939df44de1705786c545cd1bf519d47250322dBen Murdoch 17021939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderObject* current = firstChild(); 17121939df44de1705786c545cd1bf519d47250322dBen Murdoch while (current) { 17221939df44de1705786c545cd1bf519d47250322dBen Murdoch if (current->isBoxModelObject()) { 17321939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderBoxModelObject* box = toRenderBoxModelObject(current); 17421939df44de1705786c545cd1bf519d47250322dBen Murdoch 17521939df44de1705786c545cd1bf519d47250322dBen Murdoch if (box->offsetHeight() > maxHeight) 17621939df44de1705786c545cd1bf519d47250322dBen Murdoch maxHeight = box->offsetHeight(); 17721939df44de1705786c545cd1bf519d47250322dBen Murdoch 17821939df44de1705786c545cd1bf519d47250322dBen Murdoch box->style()->setVerticalAlign(BASELINE); 17921939df44de1705786c545cd1bf519d47250322dBen Murdoch } 18021939df44de1705786c545cd1bf519d47250322dBen Murdoch current = current->nextSibling(); 18121939df44de1705786c545cd1bf519d47250322dBen Murdoch } 18221939df44de1705786c545cd1bf519d47250322dBen Murdoch 18321939df44de1705786c545cd1bf519d47250322dBen Murdoch if (!maxHeight) 18421939df44de1705786c545cd1bf519d47250322dBen Murdoch maxHeight = style()->fontSize(); 18521939df44de1705786c545cd1bf519d47250322dBen Murdoch 18621939df44de1705786c545cd1bf519d47250322dBen Murdoch 18721939df44de1705786c545cd1bf519d47250322dBen Murdoch if (maxHeight > static_cast<int>(gThresholdBaseHeight * style()->fontSize())) 18821939df44de1705786c545cd1bf519d47250322dBen Murdoch style()->setPaddingBottom(Length(static_cast<int>(gRootBottomPadding * style()->fontSize()), Fixed)); 18921939df44de1705786c545cd1bf519d47250322dBen Murdoch 19021939df44de1705786c545cd1bf519d47250322dBen Murdoch 19121939df44de1705786c545cd1bf519d47250322dBen Murdoch RenderBlock::layout(); 19221939df44de1705786c545cd1bf519d47250322dBen Murdoch} 19321939df44de1705786c545cd1bf519d47250322dBen Murdoch 19421939df44de1705786c545cd1bf519d47250322dBen Murdoch} 19521939df44de1705786c545cd1bf519d47250322dBen Murdoch 19621939df44de1705786c545cd1bf519d47250322dBen Murdoch#endif // ENABLE(MATHML) 19721939df44de1705786c545cd1bf519d47250322dBen Murdoch 19821939df44de1705786c545cd1bf519d47250322dBen Murdoch 199