Kurz SVG – ořezávání a maskování

11. srpna 2004

Standard SVG obsahuje kompletní sadu grafických nástrojů a není mu cizí žádný postup využívaný profesionály. Rozdíl mezi formátem SVG a zbytkem světa, lidově řečno, se podobá rozdílu mezi Mercedesem a Trabantem. V tomto článku si tedy probereme ořezávání a maskování, což jsou velmi silné grafické nástroje, umožňující podstatně měnit vzhled dokumentu.

Maskování a ořezávání jsou sice podobné grafické operace, ale s poměrně velkým kvalitativním rozdílem:

  • Ořezové cesty (clipping paths) – dobrá představa je taková, jako by ořezávaný objekt byl podle obrysu této vektorové cesty vystřižen z papíru nůžkami. Slovy moderní počítačové grafiky, ořezový obrys představuje jednobitovou masku, pod kterou jsou maskované objekty vykresleny, zatímco vně nikoli.
  • Masky (masks) – na rozdíl od prostého ořezu může mít každý bod v masce různý stupeň průhlednosti (typicky bude maska osmibitová = 256 úrovní průhlednosti), v tomto případě tedy masku netvoří obrys maskovacích objektů, ale jas jejich výplně. Uvědomte si i vyšší výpočetní náročnost práce s maskami, to je pravděpodobně další důvod, proč jsme čekali na podobné funkce tak dlouho.

Pro lepší představu mohu vzít příklad z oblasti profesionální grafiky. Ořezové cesty, historicky samozřejmě starší, představuje například (dodnes dosti rozšířený způsob) vkládání obrázků EPS s nastavenou ořezovou cestou do sázecího programu QuarkXpress. Maskování na osobní počítače pravděpodobně přinesl jako první slavný Adobe Photoshop – sice již poměrně brzy (od verze 3), ale vkládání do stránek se zachováním průhlednosti dovolují až novější programy. Máte-li zprůhledněnou obrazovou vrstvu s maskou v souboru formátu PSD, můžete takový soubor umístit kupříkladu do InDesignu od verze 2 nebo Corelu (tuším od verze 9), kde bude maskovaný obraz stejně průhledný jako v bitmapovém editoru.

Slučování maskovaného objektu s pozadím

Takzvané slučování (simple alpha compositing) je důležitý termín, který představuje postup, jak se maskované objekty vykreslují do již existujícího pozadí. Maskovaný objekt je sloučen (smíchán) s existujícím pozadím podle následujícího vzorce, který ukazuje, jak se spočítá výsledná hodnota bodu pozadí při sloučení s bodem vykreslovaného elementu, jenž je ovlivněn maskou či průhledností:

   Pr‘ = (1 – Ea) x Pr + Er
   Pg‘ = (1 – Ea) x Pg + Eg
   Pb‘ = (1 – Ea) x Pb + Eb
   Pa‘ = 1 – (1 – Ea) x (1 – Pa)

  • Er, Eg, Eb – barva Elementu x Ea
  • Ea – průhlednost Elementu
  • Pr, Pg, Pb – barva Pozadí x Pa
  • Pa – průhlednost Pozadí
  • Pr‘, Pg‘, Pb‘ – barva Pozadí po sloučení x Pa‘
  • Pa‘ – průhlednost Pozadí po sloučení

Pozor, aby se dosáhlo elegantního zápisu, hodnoty barev jsou psány jako přednásobené (premultiplied) hodnotou průhlednosti (alpha).

Co je „viewport“

Na úvod problematiky si budeme muset zavést jeden teoretický pojem. V jakémkoli bodě kresby lze vytvořit takzvaný viewport, což je rám, který činí do něho vloženou grafiku do určité míry nezávislou na nadřazeném obsahu. Aby nějaký prvek mohl vytvořit viewport, musí mít atributy „x“, „y“, „width“ a „height“.

Především se uvnitř viewportu automaticky vytvoří nový souřadnicový systém, který bude shodný se systémem aktuálním v místě vložení s tím rozdílem, že se změní počátek souřadnic – posune se na bod „x“, „y“ – měřeno v systému aktuálním v místě vložení. Dále se logicky změní význam procentních jednotek, takže 100 % bude odpovídat plné šířce či výšce nového boxu. Souřadnicový systém lze navíc předefinovat nepovinným atributem „viewBox = (x y šířka výška)“ (viz též přehled atributů elementu svg). Dále se na takový prvek aplikují atributy „overflow“ a „clip“, popsané níže.

Nový viewport vytvářejí následující prvky svg, symbol (kdekoliv je vyvolán prvkem use), image, pattern, marker a foreignObject (vkládání obsahu v jiném XML jazyce).

Ořezávání

Ořezávání je starší a jednodušší metodou vykreslování části dokumentu určené pomocí hraniční křivky.

Atributy „overflow“ a „clip“

Přesahuje-li obsah svůj rodičovský rámec, podporuje SVG jakožto W3C standard i CSS2 atributy „overflow“ a „clip“, ovlivňující přetékání a ořezávání obsahu. Pravidla bylo nutno pro grafiku samozřejmě lehce rozšířit, ale veškerá rozšíření jsou velmi logická a znalci pravidel CSS2 si budou připadat jako doma. Oba atributy lze použít na všechny prvky, které vytváří nový „viewport“. Musíme si také uvědomit, že každý grafický prvek bude v terminologii CSS vždy typu block-level box.

  • overflow – definuje, jak a kdy bude vnitřní rám (grafický prvek) oříznut podle hranic rámu, ve kterém je obsažen. Možné hodnoty atributu jsou: visible, hidden, scroll, auto, inherit.
  • clip – specifikuje velikost a tvar ořezané oblasti (masky) následujícím způsobem: style="clip: rect(shora, zprava, zdola, zleva);". Hodnoty uvnitř závorek představují příslušné vzdáleností měřené od okrajů vnějšího rámu. CSS2 přitom povoluje pouze pravoúhlý ořez. Vidíme, že se počítá s budoucí možností ořezávat i jinými tvary než obdélníkem, použitý zápis je ale bohužel s SVG nekompatibilní.

Vytvoření ořezové cesty

Ořezová cesta se definuje uvnitř prvku clipPath. Používá se odkazováním pomocí lokální URI v atributu „clip-path“, který přidáme k prvkům, jež chceme oříznout. Lze provádět dokonce takové kejkle, jako například aplikovat ořez v atributu „clip-path“ na jiný element clipPath.

Element clipPath může obsahovat vektorové prvky path a text, základní tvary typu circle a knihovní objekty use (odkazují-li pouze na prvky uvedených povolených typů). Sám o sobě se nevykreslí.

Atributy prvku clipPath

Prvek clipPath může nést následující atributy:

  • id – standardní identifikátor objektu
  • clipPathUnits – (nepovinný) vybere jeden ze dvou možných souřadnicových systémů pro grafické prvky masky; možné hodnoty: userSpaceOnUse (výchozí), objectBoundingBox. V případě tohoto atributu opakovaně doporučuji věnovat extra pozornost následujícím hodnotám. Existuje totiž mnoho případů, kdy z hlediska přehlednosti a elegance zápisu je výhodné používat souřadnice relativní vůči velikosti aktuálně zpracovávaného objektu – jako autoři dokumentu pak například nemusíte měnit velikost šipek na konci čar, když se změní šířka dotyčné čáry.
    • „userSpaceOnUse“ – použije se aktuální systém souřadnic ve kterých je současný zpracovávaný objekt definován či kreslen.
    • „objectBoundingBox“ – tato hodnota aktivuje souřadnicový systém orientovaný uvnitř rámečku ohraničujícího konkrétní právě zpracovávaný objekt – souřadnice (0,0), respektive (0%,0%), jsou v levém horním rohu a (1,1), respektive (100%,100%), v pravém spodním rohu ohraničení objektu; jinými slovy – tento souřadnicový systém se přizpůsobuje velikosti našeho objektu
  • clip-rule – (nepovinný) je nutno aplikovat na vektorové objekty uvnitř clipPath; má identický význam s „fill-rule“ (viz atributy definující vyplňování ploch); možné hodnoty: nonzero (výchozí), evenodd, inherit

<g>
   <clipPath id=“orez_cesta“>
      <path d=“…“ clip-rule=“evenodd“ />
   </clipPath>
   <rect clip-path=“url(#orez_cesta)“ … />
</g>

Aplikace ořezu

Vlastní použití ořezové cesty je po všech definicích už hračkou – ořezávaný objekt (skupina objektů) pouze dostane navíc atribut clip-path="url(#orez_cesta)" odkazující na nějaké lokální URI.

<?xml version=“1.0″ encoding=“UTF-8″?>
<!DOCTYPE svg PUBLIC „-//W3C//DTD SVG 1.1 Basic//EN“
  „http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd“>
<svg version=“1.1″ xmlns=“http://www.w3.org/2000/svg“
     xmlns:xlink=“http://www.w3.org/1999/xlink“
     width=“320px“ viewBox=“0 0 480 360″>
  <title>6.3.3 Orezova cesta</title>
  <defs>
    <!– bude se orezavat nasledujicim napisem –>
    <clipPath id=“orez“ clipPathUnits=“userSpaceOnUse“>
      <text x=“40″ y=“270″
            font-size=“100″ font-family=“Helvetica“>
        Clip Test
      </text>
    </clipPath>
  </defs>
  <!– nejdrive zrojove objekty pro lepsi predstavu –>
  <image xlink:href=“checker.png“ x=“40″ y=“20″
         width=“400px“ height=“128px“ />
  <text x=“40″ y=“120″ font-size=“100″
        font-family=“Helvetica“ fill=“yellow“>
    Clip Test
  </text>
  <!– oriznuty obraz –>
  <image xlink:href=“checker.png“ x=“40″ y=“170″
         width=“400px“ height=“128px“ clip-path=“url(#orez)“/>
  <!– obrys platna –>
  <rect x=“1″ y=“1″ width=“478″ height=“358″
        fill=“none“ stroke=“blue“/>
</svg>

Zobrazení ořezávání v SVG
Zobrazení ořezávání v SVG (originální SVG, cca 1 kB)

Maskování

Maskování v normě SVG znamená, že libovolný grafický objekt nebo skupina může být použita jako takzvaná maska průhlednosti (alpha mask) na jakýkoli jiný objekt či skupinu při jejím slučování s již vykresleným pozadím.

Na rozdíl od prostého ořezu může mít každý bod v masce různý stupeň průhlednosti (typicky bude maska osmibitová = 256 úrovní průhlednosti) – masku netvoří obrys maskovacích objektů, ale jejich kresba, tedy přesněji jas jejich výplně.

Vytvoření masky

Masku definujeme pomocí prvku mask. Poté je aplikována na grafiku připojením odkazu v atributu „mask“, vloženého do konkrétního objektu či skupiny. Pokud jste již prostudovali ořezávání pomocí cesty, určitě vidíte formální shodnost maskování s ořezávací operací (clipPath = mask, clip-path = mask).

<g>
   <mask id=“maska“>
      <path d=“…“ />
   </mask>
   <rect mask=“url(#maska)“ … />
</g>

Element mask již může obsahovat prvky libovolného typu – včetně image, který nebyl v předchozím případě povolen – a sám o sobě se mask rovněž nevykreslí. Praktická realizace bude vypadat tak, že se maskovací objekty vykreslí do pomocného alfa kanálu (inicializovaného na „průhlednou“ černou) a následně se maskovaný objekt nebo skupina, po svém kompletním vykreslení, sloučí s pozadím se započtením hodnot z připraveného alfa kanálu.

Atributy prvku mask

Prvek clipPath může nést následující atributy:

  • id – standardní identifikátor objektu
  • maskUnits – (nepovinný) typ souřadnicového systému pro určení velikosti alfa kanálu masky; možné hodnoty: userSpaceOnUse, objectBoundingBox (výchozí)
  • maskContentUnits – (nepovinný) typ souřadnicového systému pro obsah masky; možné hodnoty: userSpaceOnUse (výchozí), objectBoundingBox
  • x, y – (nepovinný) levý horní roh alfa bufferu; výchozí hodnoty: -10%
  • width, height – (nepovinná) šířka a výška alfa bufferu; výchozí hodnoty: 120%

Aplikování masky

Použití masky je již naprosto triviální – maskovaný objekt (skupina objektů) pouze dostane navíc atribut mask="url(#maska)" s lokálním URI odkazem na vytvořenou masku.

<?xml version=“1.0″ standalone=“no“?>
<!DOCTYPE svg PUBLIC „-//W3C//DTD SVG 1.1//EN“
  „http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd“>
<svg width=“320px“ viewBox=“0 0 800 300″ version=“1.1″
     xmlns=“http://www.w3.org/2000/svg“
     xmlns:xlink=“http://www.w3.org/1999/xlink“>
  <title>6.4.2 Maska</title>
  <desc>
    Modry text na fialovem pozadi maskovany gradientem
    (opet zduraznuji spravne pouziti ‚defs‘).
  </desc>
  <defs>
    <linearGradient id=“Gradient“ gradientUnits=“userSpaceOnUse“
                    x1=“0″ y1=“0″ x2=“800″ y2=“0″>
      <stop offset=“0″ stop-color=“white“ stop-opacity=“0″ />
      <stop offset=“1″ stop-color=“white“ stop-opacity=“1″ />
    </linearGradient>
    <mask id=“Mask“ maskUnits=“userSpaceOnUse“
          x=“0″ y=“0″ width=“800″ height=“300″>
    <rect x=“0″ y=“0″ width=“800″ height=“300″
          fill=“url(#Gradient)“ />
    </mask>
  </defs>
  <!– fialove pozadi –>
  <rect x=“0″ y=“0″ width=“800″ height=“300″ fill=“plum“ />
  <text x=“400″ y=“200″ text-anchor=“middle“
        font-family=“Helvetica“ font-size=“100″
        fill=“blue“ mask=“url(#Mask)“ >
    Maskovany text
  </text>
  <!– nakresli pouze cerny obrys textu –>
  <text x=“400″ y=“200″ text-anchor=“middle“
        font-family=“Helvetica“ font-size=“100″
        fill=“none“ stroke=“black“ >
    Maskovany text
  </text>
</svg>

Zobrazení maskování v SVG
Zobrazení maskování v SVG (originální SVG, cca 1 kB)

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek missnet.cz
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *