/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "SVGPointList.h" #include "SVGContentUtils.h" #include "nsCharSeparatedTokenizer.h" #include "nsContentUtils.h" #include "nsTextFormatter.h" namespace mozilla { nsresult SVGPointList::CopyFrom(const SVGPointList& rhs) { if (!mItems.Assign(rhs.mItems, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; } void SVGPointList::GetValueAsString(nsAString& aValue) const { aValue.Truncate(); char16_t buf[50]; uint32_t last = mItems.Length() - 1; for (uint32_t i = 0; i < mItems.Length(); ++i) { // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY), // but it's not possible to always avoid trailing zeros. nsTextFormatter::snprintf(buf, std::size(buf), u"%g,%g", double(mItems[i].mX), double(mItems[i].mY)); // We ignore OOM, since it's not useful for us to return an error. aValue.Append(buf); if (i != last) { aValue.Append(' '); } } } nsresult SVGPointList::SetValueFromString(const nsAString& aValue) { SVGPointList temp; bool oddNumberOfValues = false; nsCharSeparatedTokenizerTemplate tokenizer(aValue, ','); while (tokenizer.hasMoreTokens()) { const nsAString& token = tokenizer.nextToken(); nsAString::const_iterator iter, end; token.BeginReading(iter); token.EndReading(end); float x, y; if (!SVGContentUtils::ParseNumber(iter, end, x)) { return NS_ERROR_DOM_SYNTAX_ERR; } if (iter == end) { if (tokenizer.hasMoreTokens()) { if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) { return NS_ERROR_DOM_SYNTAX_ERR; } temp.AppendItem(SVGPoint(x, y)); } else { // Drop the last odd co-ordinate and use the rest. oddNumberOfValues = true; } } else { // It's possible for the token to be 10-30 which has // no separator but needs to be parsed as 10, -30 const nsAString& leftOver = Substring(iter, end); if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) { return NS_ERROR_DOM_SYNTAX_ERR; } temp.AppendItem(SVGPoint(x, y)); } } if (!oddNumberOfValues && tokenizer.separatorAfterCurrentToken()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } mItems = std::move(temp.mItems); return NS_OK; } } // namespace mozilla