1521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Copyright (C) 2013 Google Inc. All rights reserved. 2521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// 3521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Redistribution and use in source and binary forms, with or without 4521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// modification, are permitted provided that the following conditions are 5521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// met: 6521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// 7521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// * Redistributions of source code must retain the above copyright 8521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// notice, this list of conditions and the following disclaimer. 9521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// * Redistributions in binary form must reproduce the above 10521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 11521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// in the documentation and/or other materials provided with the 12521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// distribution. 13521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 14521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// contributors may be used to endorse or promote products derived from 15521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// this software without specific prior written permission. 16521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// 17521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 29521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "config.h" 30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/StrokeData.h" 311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/OwnPtr.h" 321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/PassOwnPtr.h" 33521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 35521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 36521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static const int dashRatio = 3; // Ratio of the length of a dash to its width. 37521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 38521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void StrokeData::setLineDash(const DashArray& dashes, float dashOffset) 39521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 40521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // FIXME: This is lifted directly off SkiaSupport, lines 49-74 41521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // so it is not guaranteed to work correctly. 42521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) size_t dashLength = dashes.size(); 43521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (!dashLength) { 44521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // If no dash is set, revert to solid stroke 45521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // FIXME: do we need to set NoStroke in some cases? 46521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) m_style = SolidStroke; 477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch m_dash.clear(); 48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) return; 49521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 50521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 51521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) size_t count = !(dashLength % 2) ? dashLength : dashLength * 2; 521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) OwnPtr<SkScalar[]> intervals = adoptArrayPtr(new SkScalar[count]); 53521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 54521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) for (unsigned i = 0; i < count; i++) 55521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) intervals[i] = dashes[i % dashLength]; 56521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 5710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch m_dash = adoptRef(SkDashPathEffect::Create(intervals.get(), count, dashOffset)); 58521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 59521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 60d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void StrokeData::setupPaint(SkPaint* paint, int length) const 61521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 62521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) paint->setStyle(SkPaint::kStroke_Style); 63d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) paint->setStrokeWidth(SkFloatToScalar(m_thickness)); 64521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) paint->setStrokeCap(m_lineCap); 65521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) paint->setStrokeJoin(m_lineJoin); 66521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) paint->setStrokeMiter(SkFloatToScalar(m_miterLimit)); 67521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 68d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) setupPaintDashPathEffect(paint, length); 69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 70d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void StrokeData::setupPaintDashPathEffect(SkPaint* paint, int length) const 72d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 73d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) float width = m_thickness; 74521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (m_dash) { 757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch paint->setPathEffect(m_dash.get()); 76521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } else { 77521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) switch (m_style) { 78521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case NoStroke: 79521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case SolidStroke: 80521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case DoubleStroke: 81521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case WavyStroke: // FIXME: https://code.google.com/p/chromium/issues/detail?id=229574 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) paint->setPathEffect(0); 83d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) return; 84521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case DashedStroke: 85521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) width = dashRatio * width; 86521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Fall through. 87521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) case DottedStroke: 88521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Truncate the width, since we don't want fuzzy dots or dashes. 89521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) int dashLength = static_cast<int>(width); 90521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Subtract off the endcaps, since they're rendered separately. 91521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) int distance = length - 2 * static_cast<int>(m_thickness); 92521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) int phase = 1; 93521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (dashLength > 1) { 94521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Determine how many dashes or dots we should have. 95521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) int numDashes = distance / dashLength; 96521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) int remainder = distance % dashLength; 97521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Adjust the phase to center the dashes within the line. 98521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (numDashes % 2) { 99521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Odd: shift right a full dash, minus half the remainder. 100521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) phase = dashLength - remainder / 2; 101521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } else { 102521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Even: shift right half a dash, minus half the remainder. 103521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) phase = (dashLength - remainder) / 2; 104521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 105521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 106521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) SkScalar dashLengthSk = SkIntToScalar(dashLength); 107521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) SkScalar intervals[2] = { dashLengthSk, dashLengthSk }; 10810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch RefPtr<SkDashPathEffect> pathEffect = adoptRef(SkDashPathEffect::Create(intervals, 2, SkIntToScalar(phase))); 1097757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch paint->setPathEffect(pathEffect.get()); 110521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 111521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 112521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 113521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 114e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace blink 115