SVGPointList.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* -*- Mode: C++; tab-width: 8; 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. #include "mozilla/ArrayUtils.h"
  6. #include "SVGPointList.h"
  7. #include "nsCharSeparatedTokenizer.h"
  8. #include "nsTextFormatter.h"
  9. #include "SVGContentUtils.h"
  10. namespace mozilla {
  11. nsresult
  12. SVGPointList::CopyFrom(const SVGPointList& rhs)
  13. {
  14. if (!mItems.Assign(rhs.mItems, fallible)) {
  15. return NS_ERROR_OUT_OF_MEMORY;
  16. }
  17. return NS_OK;
  18. }
  19. void
  20. SVGPointList::GetValueAsString(nsAString& aValue) const
  21. {
  22. aValue.Truncate();
  23. char16_t buf[50];
  24. uint32_t last = mItems.Length() - 1;
  25. for (uint32_t i = 0; i < mItems.Length(); ++i) {
  26. // Would like to use aValue.AppendPrintf("%f,%f", item.mX, item.mY),
  27. // but it's not possible to always avoid trailing zeros.
  28. nsTextFormatter::snprintf(buf, ArrayLength(buf),
  29. u"%g,%g",
  30. double(mItems[i].mX), double(mItems[i].mY));
  31. // We ignore OOM, since it's not useful for us to return an error.
  32. aValue.Append(buf);
  33. if (i != last) {
  34. aValue.Append(' ');
  35. }
  36. }
  37. }
  38. nsresult
  39. SVGPointList::SetValueFromString(const nsAString& aValue)
  40. {
  41. // The spec says that the list is parsed and accepted up to the first error
  42. // encountered, so we must call CopyFrom even if an error occurs. We still
  43. // want to throw any error code from setAttribute if there's a problem
  44. // though, so we must take care to return any error code.
  45. nsresult rv = NS_OK;
  46. SVGPointList temp;
  47. nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
  48. tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
  49. while (tokenizer.hasMoreTokens()) {
  50. const nsAString& token = tokenizer.nextToken();
  51. RangedPtr<const char16_t> iter =
  52. SVGContentUtils::GetStartRangedPtr(token);
  53. const RangedPtr<const char16_t> end =
  54. SVGContentUtils::GetEndRangedPtr(token);
  55. float x;
  56. if (!SVGContentUtils::ParseNumber(iter, end, x)) {
  57. rv = NS_ERROR_DOM_SYNTAX_ERR;
  58. break;
  59. }
  60. float y;
  61. if (iter == end) {
  62. if (!tokenizer.hasMoreTokens() ||
  63. !SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) {
  64. rv = NS_ERROR_DOM_SYNTAX_ERR;
  65. break;
  66. }
  67. } else {
  68. // It's possible for the token to be 10-30 which has
  69. // no separator but needs to be parsed as 10, -30
  70. const nsAString& leftOver = Substring(iter.get(), end.get());
  71. if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) {
  72. rv = NS_ERROR_DOM_SYNTAX_ERR;
  73. break;
  74. }
  75. }
  76. temp.AppendItem(SVGPoint(x, y));
  77. }
  78. if (tokenizer.separatorAfterCurrentToken()) {
  79. rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma
  80. }
  81. nsresult rv2 = CopyFrom(temp);
  82. if (NS_FAILED(rv2)) {
  83. return rv2; // prioritize OOM error code over syntax errors
  84. }
  85. return rv;
  86. }
  87. } // namespace mozilla