Загрузка данных


Добавьте к классам `Text`, `Circle` и `Polyline` SVG-библиотеки поддержку следующих методов:

- `SetFillColor(Color color)` задаёт значение свойства [`fill`](https://www.w3.org/TR/SVG/painting.html#FillProperty) — цвет заливки. По умолчанию свойство не выводится.
- `SetStrokeColor(Color color)` задаёт значение свойства [`stroke`](https://www.w3.org/TR/SVG/painting.html#StrokeProperty) — цвет контура. По умолчанию свойство не выводится.
- `SetStrokeWidth(double width)` задаёт значение свойства [`stroke-width`](https://www.w3.org/TR/SVG/painting.html#StrokeWidthProperty) — толщину линии. По умолчанию свойство не выводится.
- `SetStrokeLineCap(StrokeLineCap line_cap)` задаёт значение свойства [`stroke-linecap`](https://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty)— тип формы конца линии. По умолчанию свойство не выводится.
- `SetStrokeLineJoin(StrokeLineJoin line_join)` задаёт значение свойства [`stroke-linejoin`](https://www.w3.org/TR/SVG/painting.html#StrokeLinejoinProperty) — тип формы соединения линий. По умолчанию свойство не выводится.

Эти методы должны поддерживать method chaining, то есть возвращать ссылку на тип объекта, у которого были вызваны.

Тип `Color` объявите на основе типа `std::string`. Также объявите константу `NoneColor`, имеющую значение `none`:

```
namespace svg {
...
using Color = std::string;

// Объявив в заголовочном файле константу со спецификатором inline,
// мы сделаем так, что она будет одной на все единицы трансляции,
// которые подключают этот заголовок.
// В противном случае каждая единица трансляции будет использовать свою копию этой константы
inline const Color NoneColor{"none"};
...
} 
```

Типы `StrokeLineCap` и `StrokeLineJoin` объявляются с использованием `enum`:

```
namespace svg {
...
enum class StrokeLineCap {
    BUTT,
    ROUND,
    SQUARE,
};

enum class StrokeLineJoin {
    ARCS,
    BEVEL,
    MITER,
    MITER_CLIP,
    ROUND,
};
...
} // namespace svg 
```

Перегрузите для `StrokeLineCap` и `StrokeLineJoin` операцию `<<` для вывода в `std::ostream` как показано ниже.

|`StrokeLineCap`|Формат вывода|
|---|---|
|`BUTT`|`butt`|
|`ROUND`|`round`|
|`SQUARE`|`square`|

|`StrokeLineJoin`|Формат вывода|
|---|---|
|`ARCS`|`arcs`|
|`BEVEL`|`bevel`|
|`MITER`|`miter`|
|`MITER_CLIP`|`miter-clip`|
|`ROUND`|`round`|

Класс `shapes::Snowman` должен использовать следующие цвета:

- Заливка: `rgb(240,240,240)`
- Контур: `black`

Класс `shapes::Star` должен использовать следующие цвета:

- Заливка: `red`
- Контур: `black`

Класс `shapes::Triangle` оставьте без изменений.

Пример использования:

```
int main() {
    using namespace svg;
    using namespace shapes;
    using namespace std;

    vector<unique_ptr<svg::Drawable>> picture;
    picture.emplace_back(make_unique<Triangle>(Point{100, 20}, Point{120, 50}, Point{80, 40}));
    picture.emplace_back(make_unique<Star>(Point{50.0, 20.0}, 10.0, 4.0, 5));
    picture.emplace_back(make_unique<Snowman>(Point{30, 20}, 10.0));

    svg::Document doc;
    DrawPicture(picture, doc);

    const Text base_text =  //
        Text()
            .SetFontFamily("Verdana"s)
            .SetFontSize(12)
            .SetPosition({10, 100})
            .SetData("Happy New Year!"s);
    doc.Add(Text{base_text}
                .SetStrokeColor("yellow"s)
                .SetFillColor("yellow"s)
                .SetStrokeLineJoin(StrokeLineJoin::ROUND)
                .SetStrokeLineCap(StrokeLineCap::ROUND)
                .SetStrokeWidth(3));
    doc.Add(Text{base_text}.SetFillColor("red"s));

    doc.Render(cout);
} 
```

Ожидаемый результат (порядок перечисления атрибутов может отличаться):

```
<?xml version="1.0" encoding="UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <polyline points="100,20 120,50 80,40 100,20" />
  <polyline points="50,10 52.3511,16.7639 59.5106,16.9098 53.8042,21.2361 55.8779,28.0902 50,24 44.1221,28.0902 46.1958,21.2361 40.4894,16.9098 47.6489,16.7639 50,10" fill="red" stroke="black"/>
  <circle cx="30" cy="70" r="20" fill="rgb(240,240,240)" stroke="black"/>
  <circle cx="30" cy="40" r="15" fill="rgb(240,240,240)" stroke="black"/>
  <circle cx="30" cy="20" r="10" fill="rgb(240,240,240)" stroke="black"/>
  <text fill="yellow" stroke="yellow" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" x="10" y="100" dx="0" dy="0" font-size="12" font-family="Verdana">Happy New Year!</text>
  <text fill="red" x="10" y="100" dx="0" dy="0" font-size="12" font-family="Verdana">Happy New Year!</text>
</svg> 
```

![](https://code.s3.yandex.net/CPP/%D1%8104_elegance/s10/l08/happy_new_year.png)

### Описание формата выходных данных

Требования к содержимому, выводимому методом `svg::Document::Render`, аналогичны требованиям из предыдущего урока.

### Ограничения

Ограничения допускают любое адекватное линейное решение: за одну секунду нужно обрабатывать порядка 10 000 вызовов конструкторов объектов и методов выставления свойств, а также один вызов метода `svg::Document::Render`.

Гарантируется, что при тестировании тренажёр будет передавать валидные параметры в методы классов и их конструкторы. Поэтому усложнять код проверками не нужно.

### Что отправлять на проверку

Код библиотеки должен располагаться в файлах `svg.h` и `svg.cpp`. Файл `main.cpp` должен содержать классы `Triangle`, `Snowman` и `Star` в пространстве имён `shapes` и необходимые для их работы функции. Функция `main` будет заменена на версию из тренажёра.

### Как будет тестироваться ваш код

Тренажёр проверит работу классов `shapes::Triangle`, `shapes::Snowman` и `shapes::Star`, а также классов объектов библиотеки `svg`.