Specyfikacja otwartego formatu

Rozszerzenie OXS: hardanger

Rozszerzenie formatu wzorów OXS (Open Cross Stitch) o haft hardanger — klostry, pasma cięcia, słupki, wypełnienia, ściegi powierzchniowe, picoty i koraliki — zapisane bez zmiany choćby jednego bajtu standardowych danych OXS. Każdy może je zaimplementować, w dowolnym programie, bez pytania o zgodę.

Wersja rozszerzenia
1
Rodzina
hardanger, wersja 1
Vendor
obateam
Status
stabilna, wdrożona
Ten dokument
2026-09-11
Format bazowy
OXS

Słowa MUST, MUST NOT, SHOULD i MAY mają zwykłe znaczenie normatywne i celowo zostają po angielsku. Wszystkie nazwy elementów i atrybutów są dosłowne.

1. Zasady konstrukcyjne

  1. Tylko nowe elementy top-level. Rozszerzenie MUST NOT dodawać atrybutów do istniejących elementów OXS ani zmieniać znaczenia istniejących danych. Jedyna gwarancja, jaką daje XML, to pomijanie nieznanych elementów — nieznany atrybut na znanym elemencie nie jest bezpieczny.
  2. Sekcje standardowe nietknięte. Pełne krzyżyki zostają w <fullstitches>, koraliki i węzełki w <ornaments_inc_knots_and_beads>, kontury w <backstitches>. Rozszerzenie tylko dodaje.
  3. Plik jest samoopisujący. Wypełnienie niesie id katalogu oraz rozwiązaną geometrię (§7.4). Ten sam plik MUST renderować się identycznie po aktualizacji katalogu wypełnień u czytnika.
  4. Geometria wyliczalna nie jest zapisywana. Klasyfikacja regionów, pozycje kropek cięcia i kolejność faz są wyliczane (§9). Zapis nadmiarowy = drugie źródło prawdy.
  5. Współrzędne w nitkach, całkowite. Wyjątkiem są rozwiązane ścieżki i dwa rekordy zakotwiczone w punkcie (picot, koralik), gdzie ułamki są dozwolone — to geometria nitki w powietrzu, nie pozycja na siatce.

2. Układ współrzędnych

0 2 4 6 8 10 0 2 4 6 8 x="2" y="2" count = 5 ściegów span = 4 nitki · bbox 4×4
Jeden klostr: <stx_satin x="2" y="2" axis="h" count="5" span="4" role="kloster">. Pięć ściegów zajmuje kolumny węzłów 2…6 — czyli cztery przedziały nitkowe, nie pięć.

Dlaczego nitki. Hardanger jest natywnie liczony w nitkach, a threadsperunit to jedna deklarowana konwersja. Współrzędna nitkowa jest przy tym tożsama z reprezentacją w pamięci implementacji (pół-komórki fixed-point ×2), więc między plikiem a modelem nie ma żadnego przeliczania.

3. Deklaracja rozszerzenia

<stx_extensions version="1" vendor="obateam"
                spec="https://stitchtracker.obateam.com/oxs-ext/1">
  <stx_feature id="hardanger" version="1" required="true" fallback="comment"
               summary="12 kloster blocks, 6 cut bands, 12 bars, 5 fillings, 4 eyelets, 0 beads, 2 straight stitches, 4 picots" />
</stx_extensions>
AtrybutZnaczenie
idRodzina technik. Wersja 1 definiuje dokładnie jedną: hardanger.
versionWersja definicji tej rodziny, niezależna od stx_extensions/@version. Mówi, czego plik faktycznie wymaga od czytnika — patrz §12.
requiredtrue = bez wsparcia wzór jest niekompletny; czytnik SHOULD ostrzec użytkownika.
fallbackcomment | none. Jak treść jest zasygnalizowana czytnikowi bez wsparcia (§4).
summaryGenerowane podsumowanie licznikowe, po angielsku, do pokazania użytkownikowi. Informacyjne — czytnik MUST NOT parsować go jako danych.

Writer referencyjny emituje osiem liczników w stałej kolejności: kloster blocks, cut bands, bars, fillings, eyelets (wszystkie <stx_stitch>, nie tylko oczka), beads, straight stitches, picots. fallback="none" znaczy, że w pliku NIE MA markera — tak zapisuje się blok bez zapisywalnych rekordów.

<stx_feature> jest punktem rozszerzalności. Kolejne rodziny technik (silkribbon, drawnthread, blackwork) dostają własny <stx_feature> i własny blok top-level. Wersja 1 ich nie definiuje.

4. Fallback i wykrywanie utraty danych

Przy fallback="comment" writer MUST wygenerować dokładnie jeden <commentbox>-marker, którego tekst zaczyna się od stałego sentinela HARDANGER:.

<commentboxes>
  <commentbox boxleft="4" boxtop="4" boxwidth="14" boxheight="14"
              boxwords="HARDANGER: 12 kloster blocks, 6 cut bands, 12 bars, 5 fillings, 4 eyelets, 0 beads, 2 straight stitches, 4 picots. Chart incomplete without Hardanger support. Requires software with Hardanger support." />
</commentboxes>

Wykrywanie utraty danych. Obcy program, który wczyta i zapisze plik, wyrzuci elementy stx_* (nie zna ich), ale zachowa <commentboxes> (zna). Sentinel jest więc samowystarczalny: detekcja nie zależy od <stx_extensions>, które w takim round-tripie ginie razem z resztą stx_*.

marker HARDANGER:blok <stx_hardanger>Interpretacja
nieniePlik nigdy nie miał hardangeru.
nietakPlik kompletny (writer z fallback="none").
taktakPlik kompletny.
takniePlik STRACIŁ hardanger. Czytnik MUST ostrzec i MUST NOT cicho nadpisać oryginału.

Synchronizacja markera. Marker jest artefaktem writera, nie treścią wzoru:

Dlaczego nie cień-zarys w <backstitches>? Backstitch jest ściegiem. Cień-zarys zostałby wyhaftowany jako kontur i dałby artefakt wyglądający jak wzór, którym nie jest. Komentarz to tekst — nikt go nie wyhaftuje. Opcjonalny objecttype="stx_shadow" MAY pojawić się w przyszłej wersji jako przełącznik eksportu z domyślnym OFF; wersja 1 go nie definiuje.

5. Blok stx_hardanger

Dokument MUST zawierać co najwyżej jeden <stx_hardanger>, jako rodzeństwo sekcji standardowych — jedno miejsce detekcji, jedno miejsce pominięcia.

<stx_hardanger unit="thread" threadsperunit="2" origin="node">
  <stx_threads>…</stx_threads>
  <stx_satins>…</stx_satins>
  <stx_cuts>…</stx_cuts>
  <stx_bars>…</stx_bars>
  <stx_fillings>…</stx_fillings>
  <stx_surface>…</stx_surface>
  <stx_beads>…</stx_beads>
  <stx_picots>…</stx_picots>
</stx_hardanger>

Wszystkie kolekcje są opcjonalne. Ich kolejność jest nieznacząca; czytnik MUST NOT jej zakładać.

Deklaracja układu współrzędnych jest obowiązkowa. unit="thread", origin="node" i całkowite threadsperunit ≥ 1 MUST być na bloku. Czytnik, który nie potrafi ich odczytać (brak, inna wartość, wartość spoza domeny), MUST odrzucić cały blok, a nie zgadywać domyślnych: rekord bez zadeklarowanego układu jest rekordem bez znaczenia, a nie rekordem w układzie domyślnym.

Rekordy MUST być bezpośrednimi dziećmi swojej kolekcji (jeden poziom pod blokiem). Czytnik MUST ignorować rekordy zagnieżdżone głębiej oraz — gdy plik łamie regułę jednego bloku — wszystko poza pierwszym <stx_hardanger>. Wyjątkiem jest <stx_path>, który z definicji jest dzieckiem rekordu.

6. Nici

<stx_threads>
  <stx_thread palindex="2" weight="perle8" />
  <stx_thread palindex="3" weight="perle12" />
</stx_threads>

palindex odnosi się do standardowej palety OXS. weight ∈ perle3 | perle5 | perle8 | perle12 | floss | other. Grubość nici jest realną własnością wzoru hardanger (klostry perle 8, słupki i oczka perle 12), nie kosmetyką: wpływa i na render, i na listę zakupów.

Kolekcja opisuje nici użyte w rekordach hardangeru, a nie całą paletę: nić, której wszystkie rekordy zniknęły, wypada z niej przy następnym zapisie. Koraliki są wyłączone — koralik (§7.8) nie jest nicią i nie ma grubości.

Waga wynika z produktu, nie z roli rekordu. Grubość kordonka jest częścią numeru nici („DMC Pearl 8”), więc writer wyprowadza ją z marki; reguła rzemiosła („satyna grubszą, reszta cieńszą”) mówi, KTÓRĄ nić wybrać, a nie jaką grubość ma nić już wybrana — konkretna para zależy od splotu tkaniny (22 ct → 5 + 8, 28 ct → 8 + 12). Writer SHOULD więc wyliczać wagę wyłącznie dla nici, która wpisu jeszcze nie ma, i MUST zachować wagę wczytaną z pliku: autorytatywne przeliczanie zamienia zaimportowane perle8 przy nierozpoznanej marce na other po pierwszej edycji, czyli cicho traci dane interopu.

7. Prymitywy

7.1 stx_satin — pas satynowy, w tym klostr

<stx_satin x="12" y="8" axis="h" count="5" span="4"
           palindex="2" role="kloster" dir="down" />
AtrybutZnaczenie
x, yLewy-górny węzeł bounding boxu, w nitkach.
axish = ściegi ułożone obok siebie wzdłuż x (każdy ścieg biegnie w y); v = odwrotnie.
countLiczba ściegów satynowych.
spanDługość jednego ściegu, w nitkach.
rolekloster | satin | edge
dirup | down | left | right — strona, którą pas zabezpiecza.

role="kloster" znaczy „autor tnie przy tym bloku” — to decyzja autora zapisana w rekordzie, a nie opis kształtu. Książka mówi to wprost: „klosters and longer satin stitch blocks can be put together to form cutwork areas” (s. 18), „sometimes there are more than five satin stitches to cut beside” (s. 34).

Kanoniczny klostr to count="5", span="4" — bounding box 4×4 nitki, bo pięć ściegów zajmuje kolumny węzłów x … x+4, czyli cztery przedziały nitkowe. To szczególny przypadek, nie warunek: legalne obramowanie wycięcia ma count ≥ 2 i span ≥ 1, a liczba nitek wychodzących z czoła to zawsze count − 1, więc pasma, pary i okienka liczą się tą samą matematyką. Blok jednościegowy nie oddaje żadnej nitki i obramowaniem nie jest; role="edge" (obrzeże wykończeniowe) z okienkiem nie graniczy.

Off-by-one. Kanoniczny blok to pięć ściegów przez cztery nitki. Nie cztery przez cztery, nie pięć przez pięć. Klasyczny błąd implementacji — i najczęstszy błąd początkujących przy tkaninie. Walidacja rytmu co cztery nitki dotyczy wyłącznie bloku kanonicznego: blok siedmiościegowy zajmuje sześć nitek i nie jest błędem.

dir jest znaczące dla walidacji i lustrowania, nie tylko dla renderu: wskazuje krawędź, przy której pas zabezpiecza przecięte końce nitek. Lustrowanie pasa MUST odwrócić dir.

7.2 stx_cut — pasmo usuniętych nitek

<stx_cut dir="v" x1="12" y1="12" x2="16" y2="32" derived="1" />
AtrybutZnaczenie
dirKierunek biegu usuniętych nitek: v = pionowe, h = poziome.
x1,y1,x2,y2Bounding box pasma, w nitkach; x1<x2, y1<y2.
derived1 = pasmo wyliczone z pary klostrów; 0 = jawny override autora.

To nie jest prostokąt otworu. Otwór jest skutkiem, nie daną. Pasmo opisuje fizyczną czynność: „nitki biegnące w kierunku dir w tym obszarze zostały wyciągnięte”.

Uzasadnienie. Prostokąt-otwór nie potrafi opisać obszaru, w którym usunięto nitki tylko jednego kierunku — a to dokładnie tam powstają słupki. Kratownica 3×3 okienek (9 otworów, 12 słupków, 4 skrzyżowania nienaruszonej tkaniny) wynika z 6 elementów <stx_cut> — trzech pionowych i trzech poziomych. Prostokątami otworów trzeba by ją opisać 25 elementami i nadal nie dałoby się odróżnić słupka poziomego od pionowego.

7.3 stx_bar — słupek

<stx_bar x1="12" y1="18" x2="16" y2="18" kind="woven" threads="4" palindex="3" />

x1,y1 → x2,y2 to linia środkowa pasma nitek, które przetrwały cięcie, nie bounding box. Takie pasma mają parzystą szerokość, więc linia środkowa zawsze wypada na całkowitej współrzędnej. threads = ile nitek zostało (typowo 4).

kind ∈ wrapped | woven | divided | lacedBehind | twisted | zigzag | overwrapped | buttonholed. overwrapped to słupek owinięty za gęsto na swoją długość, przez co się wybrzusza (cztery takie wokół okienka czytają się jako okrąg); buttonholed to słupek kryty ściegiem dziurkowym. Lista jest addytywna, a jej kolejność zamrożona (bajt rodzaju jest kluczem sortowania i tagiem rekordu w implementacjach — patrz §9.3); nowe rodzaje dochodzą na końcu.

Nieznana wartość kind odrzuca REKORD, nie plik. Czytnik MUST NOT podmieniać jej na wrapped: słupek o nieznanej obróbce narysowany jako owijany jest kłamstwem o robocie, a nie degradacją. Praktyczna konsekwencja: rodzaj dodany przez nowszy writer jest dla starszego czytnika niewidoczny — ten jeden słupek wypada z wykresu, reszta pliku wczytuje się normalnie.

Istnienie słupka jest wyliczalne (§9.1), ale kind to decyzja autora wzoru i MUST być zapisane. Czytnik MUST NOT zakładać wrapped przy braku elementu: brak oznacza, że autor nie określił słupka, a nie że jest owijany.

7.4 stx_filling — wypełnienie okienka

<stx_filling x1="20" y1="20" x2="24" y2="24" catalog="doves-eye"
             rot="0" mirror="0" palindex="3" weight="12">
  <stx_path closed="1">22.00,20.00 22.51,20.43 … 22.00,20.00</stx_path>
</stx_filling>
<stx_path> jest normatywny, catalog jest podpowiedzią. Renderer MUST rysować z <stx_path>. Writer MUST go wygenerować dla każdego wypełnienia. To właśnie czyni prawdziwą zasadę 3 z §1: plik nie może zacząć renderować się inaczej dlatego, że ktoś zaktualizował katalog.
Nota implementacyjna. Punkty żyją w treści tekstowej elementu, nie w atrybucie. Parsery zdarzeniowe (SAX/XMLParser), które dotąd czytały wyłącznie atrybuty, muszą dodać obsługę treści dla tego jednego elementu.

Parsowanie jest rygorystyczne, bo <stx_path> jest normatywny. Jeden błędny token unieważnia całą polilinię — geometrii normatywnej nie wolno po cichu przyciąć o punkt — a <stx_filling>, któremu nie została ani jedna poprawna polilinia, odrzuca się w całości. Inaczej „rysuj z <stx_path>” zamienia się w „rysuj z tego, co się sparsowało”. <stx_stitch> (§7.5) żyje bez ścieżek: jego geometrię niesie katalog i span.

7.5 stx_stitch — ścieg powierzchniowy

<stx_stitch x="16" y="16" catalog="eyelet" span="4"
            palindex="3" rot="0" weight="8" />

Ściegi zakotwiczone w punkcie lub kwadratowym obszarze, a nie w okienku między słupkami: oczko algierskie, ścieg czterostronny. span = rozmiar w nitkach. Elementy o złożonej geometrii MAY nieść dzieci <stx_path> na tych samych zasadach co §7.4.

catalog MUST NOT być pusty — element opisuje ścieg z katalogu. Ścieg bez wpisu w katalogu i bez kwadratowego śladu opisuje §7.6.

7.6 stx_straight — ścieg pojedynczy

<stx_straight x1="12" y1="8" x2="19" y2="15" palindex="2" />

Jeden ścieg prosty położony na nieciętej tkaninie, opisany dwoma końcami (węzły, w nitkach). Żyje w kolekcji <stx_surface> obok <stx_stitch>, ale jest osobnym elementem, bo nie ma ani id katalogu, ani kwadratowego span — a §7.5 wymaga obu.

To nie jest stx_satin z count="1". stx_satin@axis przyjmuje wyłącznie h/v, więc ścieg na skos nie ma tam jak zamieszkać bez zmiany znaczenia istniejącego atrybutu — a to byłoby zmianą łamiącą (§12).

Kąt nie jest własnością formatu. Element niesie geometrię: dwa dowolne węzły. Edytor może ograniczać gest do czterech kierunków; czytnik MUST przyjąć każdą parę węzłów. x1,y1 MUST różnić się od x2,y2 — ścieg zerowej długości nie jest ściegiem.

7.7 stx_picot — picot

<stx_picots>
  <stx_picot x="6" y="8" kind="knotted" dir="n" palindex="2" />
</stx_picots>
AtrybutZnaczenie
x,yPunkt zaczepu na hoście, w nitkach — ułamkowy.
kindknotted | looped | chain
dirn ne e se s sw w nw — kierunek wystawania glifu z hosta.
palindexNić robocza.

Picot to guzek doczepiony do istniejącej obróbki: środka słupka (wystaje w otwór), narożnika wyciętego okienka (diagonalnie w otwór) albo boku wypełnienia. Dostaje własną kolekcję zamiast atrybutu na <stx_bar>, bo hostem bywa wypełnienie — a parser strumieniowy i tak nie wiąże dzieci z rodzicem.

Format nie niesie referencji do hosta. Tak jak kropki cięcia (§9.2) są wyliczane, tak picot jest samodzielną geometrią: zaczep i kierunek wystarczają do narysowania glifu, a wybór hosta jest regułą edytora, nie pliku. Czytnik MUST przyjąć każdy legalny punkt — także taki, pod którym żadnej obróbki nie ma. Nieznana wartość kind/dir odrzuca rekord, nie plik.

Picoty z koralikiem nie używają tego elementu — koralik jest innym materiałem i idzie do §7.8.

7.8 stx_bead — koralik w ażurze

<stx_beads>
  <stx_bead x="22.0" y="20.0" palindex="6" />
</stx_beads>

Koralik będący częścią roboty hardanger — siedzący w narożniku wypełnienia albo na słupku jako picot z koralikiem. Pozycja jest w nitkach i ułamkowa, jak punkty ścieżek: przy okienku innym niż 4×4 nitki narożnik wypełnienia nie wypada na całkowitej nitce.

Ma własny element, a nie ścieżkę wypełnienia, bo koralik to inny materiał: narysowanie go ściegiem okłamałoby każdego, kto liczy materiały — lista zakupów pokazałaby więcej kordonka tam, gdzie potrzebna jest paczka koralików. Zwykłe koraliki wzoru, niezwiązane z ażurem, zostają w standardowej sekcji <ornaments_inc_knots_and_beads> (§1, zasada 2). Dlatego koralik nie ma weight (§10) i nie wchodzi do <stx_threads> (§6).

Element należy do powierzchni wersji 1 (§12), tak jak każdy inny rekord z §7.

8. Ściegi powierzchniowe a sekcje standardowe

Ścieg powierzchniowy hardanger MUST iść do <stx_surface>, nigdy do <backstitches>, nawet gdy geometrycznie dałby się wyrazić liniami. Powód: <backstitches> ma zdefiniowaną semantykę (ścieg konturowy) i własny render, którego rozszerzenie MUST NOT zmieniać.

9. Semantyka wyliczana

Wszystko w tej sekcji MUST być wyliczane przez czytnik i MUST NOT być zapisywane w pliku.

9.1 Klasyfikacja regionów

Dla punktu (x,y): v = objęty pasmem dir="v", h = objęty pasmem dir="h".

vhRegion
✓✓Otwór — brak tkaniny w obu kierunkach.
✓✗Nitki poziome przetrwały → słupek poziomy.
✗✓Nitki pionowe przetrwały → słupek pionowy.
✗✗Nienaruszona tkanina.

Granice regionów to krawędzie pasm <stx_cut>. Renderer i walidator używają tej samej funkcji.

9.2 Pozycje kropek cięcia (styl wykresu)

Kropka oznacza miejsce przecięcia nitki — czoło pasma przy klostrze — a nie obwódkę otworu. Nitkę przecina się tylko tam, gdzie klostr ją zabezpiecza, a potem wyciąga na całej długości.

Dla pasma dir="v", x1..x2, y1..y2, o n = x2 − x1 nitkach:

Analogicznie dla dir="h". Otwory wewnętrzne kratownicy nie mają kropek — tam nic nie przecinano. Reguła jest w całości wyliczalna z <stx_cut>; format nie niesie kropek.

x1=2 x2=6 y1=4 y2=8 klostr zabezpiecza końce 4 nitki wyciągnięte (dir="v") kropki w x1+k+0.5 tylko na y1 i y2
Kropki siedzą na dwóch czołach pasma, na środkach nitek — nigdy wokół otworu. Kropka, za którą nie stoi klostr, to błąd walidacji unsecuredEdge.

9.3 Kolejność kanoniczna

Wyliczany z typu rekordu, nigdy zapisywany. Bajt jest jednocześnie tagiem typu i pierwszym kluczem sortowania, a kolejność jest zamrożona — czytnik śledzący postęp per rekord indeksuje po pozycji w tej posortowanej tablicy, więc przenumerowanie rozjechałoby cudzy postęp:

0. <stx_satin>    (wszystkie role)
1. <stx_cut>
2. <stx_bar>
3. <stx_filling>
4. <stx_stitch>   (kolekcja <stx_surface>)
5. <stx_bead>
6. <stx_straight> (ta sama KOLEKCJA co <stx_stitch>, osobny typ rekordu)
7. <stx_picot>

Wewnątrz typu rekordy sortują się po pełnej zapisanej treści, zaczynając od (y, x). Sekcje standardowe OXS mają własne porządki i z tym nie interferują.

To porządek kanoniczny formatu, a nie kolejność haftowania. Ta idzie z rzemiosła i wygląda inaczej: satyna i klostry → ściegi ciągnione → ściegi powierzchniowe → krzyżyki i kontury → cięcie i wyciągnięcie nitek → słupki → wypełnienia → ozdoby. Ściegi powierzchniowe — w tym <stx_straight>, który leży na całej tkaninie — przypadają więc przed cięciem, a nie po nim. Autor MAY opisać własną kolejność w standardowym properties/@instructions; format nie dodaje na nią pola.

10. Wagi jednostek pracy

weight to przybliżona liczba przewleczeń igły. Jest statyczna i MUST być w pliku, żeby czytnik mógł policzyć postęp albo czas bez katalogu wypełnień.

Jednostkaweight
Pełny krzyżyk (dla odniesienia)1
Ścieg pojedynczy (stx_straight)1
Picot (stx_picot)1
Klostr (5 ściegów)5
Słupek owijany, 4 nitki8
Słupek skręcany, 4 nitki8
Linia zygzakowata, 4 nitki6
Oczko algierskie 16-punktowe8
Dove's eye12
Square filet16
Koralik (stx_bead)— liczony w sztukach, nie w przewleczeniach

Wypełnienia katalogowe niosą własny atrybut weight na rekordzie, więc czytnik nigdy nie potrzebuje tej tabeli dla typów spoza niej. Czytnik liczący procent postępu SHOULD używać ważonej sumy; dla wzoru bez hardangeru wszystkie wagi = 1, więc wynik jest bit-identyczny z liczeniem po sztukach.

11. Zgodność

Czytnik minimalny (bez wsparcia hardangeru)

Czytnik pełny

Writer

12. Polityka wersjonowania

Rodzina hardanger w wersji 1 to CAŁA powierzchnia opisana w §5–§9: satyny, pasma cięcia, słupki z ośmioma rodzajami, wypełnienia, ściegi powierzchniowe, koraliki, ściegi pojedyncze i picoty. Plik zgodny z tym dokumentem MUST deklarować version="1" niezależnie od tego, które z tych rekordów niesie.

Mechanizm adaptacyjny włącza się przy pierwszym dodatku po publikacji. Od tego momentu stx_feature/@version MUST być najwyższą wersją, której plik faktycznie wymaga, a nie najwyższą, którą writer umie: plik bez rekordów z wersji 2 MUST nadal deklarować 1, bo przy required="true" stałe 2 kazałoby ostrożnemu czytnikowi wersji 1 odrzucić wzór, który poza tym jest w całości wersji 1 — czyli plik, który otwierał dzień wcześniej. Czytnik trzyma najwyższą obsługiwaną wersję rodziny i plik deklarujący więcej raportuje jako nieobsługiwany, zamiast rysować go po cichu niepełnie.

13. Poza zakresem wersji 1

14. Plik referencyjny

Prawdziwy wzór wyeksportowany ze StitchTracker Studio, nie ręcznie pisana próbka: 27×27 komórek, dwa medaliony, 32 klostry, 12 pasm cięcia, 12 słupków i 6 wypełnień (maltese flower i twisted Y, każde z rozwiązaną, wielopolilinijną geometrią), a do tego 264 kontury, 3 pełne krzyżyki i 5 koralików w sekcjach standardowych. Otwarty w czytniku bez wsparcia hardangeru pokaże krzyżykowy szkielet, kontury i marker-komentarz; w czytniku pełnym — cały ażur.

⬇ hardanger-demo.oxs (115 KB)

Dzisiejsze implementacje: StitchTracker (czytnik, iPadOS/iOS) i StitchTracker Studio (writer). Jeśli implementujesz to rozszerzenie u siebie i coś tu jest niejednoznaczne albo potrzebujesz wektora testowego na przypadek, którego plik referencyjny nie pokrywa — napisz na krzysiekobateam@gmail.com. Poprawki do tego dokumentu są mile widziane.