Gambaran umum kuas

Gambaran umum ini menjelaskan cara membuat dan menggunakan objek ID2D1SolidColorBrush, ID2D1LinearGradientBrush, ID2D1RadialGradientBrush, dan OBJEK ID2D1BitmapBrush untuk melukis area dengan warna solid, gradien, dan bitmap. Ini berisi bagian berikut.

Prasyarat

Gambaran umum ini mengasumsikan bahwa Anda terbiasa dengan struktur aplikasi Direct2D dasar, seperti yang dijelaskan dalam Membuat aplikasi Direct2D sederhana.

Jenis kuas

Kuas "melukis" area dengan outputnya. Kuas yang berbeda memiliki berbagai jenis output. Direct2D menyediakan empat jenis kuas: ID2D1SolidColorBrush melukis area dengan warna solid, ID2D1LinearGradientBrush dengan gradien linier, ID2D1RadialGradientBrush dengan gradien radial, dan ID2D1BitmapBrush dengan bitmap.

Catatan

Dimulai dengan Windows 8, Anda juga dapat menggunakan ID2D1ImageBrush, yang mirip dengan kuas bitmap, tetapi Anda juga dapat menggunakan primitif.

Semua kuas mewarisi dari ID2D1Brush dan berbagi serangkaian fitur umum (mengatur dan mendapatkan keburaman, dan mengubah kuas); mereka dibuat oleh ID2D1RenderTarget dan merupakan sumber daya yang bergantung pada perangkat: aplikasi Anda harus membuat kuas setelah menginisialisasi target render tempat kuas akan digunakan, dan membuat ulang kuas setiap kali target render perlu dibuat ulang. (Untuk informasi selengkapnya tentang sumber daya, lihat Gambaran Umum Sumber Daya.)

Ilustrasi berikut menunjukkan contoh masing-masing jenis kuas yang berbeda.

ilustrasi efek visual dari kuas warna solid, kuas gradien linier, kuas gradien radial, dan kuas bitmap

Dasar-dasar warna

Sebelum Anda melukis dengan ID2D1SolidColorBrush atau sikat gradien, Anda perlu memilih warna. Dalam Direct2D, warna diwakili oleh struktur D2D1_COLOR_F (yang sebenarnya hanyalah nama baru untuk struktur yang digunakan oleh Direct3D, D3DCOLORVALUE).

Sebelum Windows 8, D2D1_COLOR_F menggunakan pengodean sRGB. Pengodean sRGB membagi warna menjadi empat komponen: merah, hijau, biru, dan alfa. Setiap komponen diwakili oleh nilai titik float dengan rentang normal 0,0 hingga 1,0. Nilai 0,0 menunjukkan tidak adanya warna tersebut secara lengkap, sementara nilai 1,0 menunjukkan bahwa warna sepenuhnya ada. Untuk komponen alfa, 0,0 mewakili warna yang sepenuhnya transparan dan 1,0 mewakili warna yang sepenuhnya buram.

Mulai dari Windows 8, D2D1_COLOR_F juga menerima pengodean scRGB. scRGB adalah superset yang memungkinkan nilai warna di atas 1,0 dan di bawah 0,0.

Untuk menentukan warna, Anda dapat menggunakan struktur D2D1_COLOR_F dan menginisialisasi bidangnya sendiri, atau Anda dapat menggunakan kelas D2D1::ColorF untuk membantu Anda membuat warna. Kelas ColorF menyediakan beberapa konstruktor untuk menentukan warna. Jika nilai alfa tidak ditentukan dalam konstruktor, nilai tersebut default ke 1,0.

  • Gunakan konstruktor ColorF(Enum, FLOAT) untuk menentukan warna yang telah ditentukan dan nilai saluran alfa. Nilai saluran alfa berkisar antara 0,0 hingga 1,0, di mana 0,0 mewakili warna yang sepenuhnya transparan dan 1,0 mewakili warna yang sepenuhnya buram. Ilustrasi berikut menunjukkan beberapa warna yang telah ditentukan sebelumnya dan setara heksadesimalnya. Untuk daftar lengkap warna yang telah ditentukan sebelumnya, lihat bagian Konstanta warna dari kelas ColorF .

    ilustrasi warna yang telah ditentukan sebelumnya

    Contoh berikut membuat warna yang telah ditentukan sebelumnya dan menggunakannya untuk menentukan warna ID2D1SolidColorBrush.

hr = m_pRenderTarget->CreateSolidColorBrush(
    D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
    &m_pBlackBrush
    );
  • Gunakan konstruktor ColorF(FLOAT, FLOAT, FLOAT, FLOAT) untuk menentukan warna dalam urutan merah, hijau, biru, dan alfa, di mana setiap elemen memiliki nilai antara 0,0 dan 1,0.

    Contoh berikut menentukan nilai merah, hijau, biru, dan alfa untuk warna.

    ID2D1SolidColorBrush *pGridBrush = NULL;
    hr = pCompatibleRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0.93f, 0.94f, 0.96f, 1.0f)),
        &pGridBrush
        );
  • Gunakan konstruktor ColorF(UINT32, FLOAT) untuk menentukan nilai heksadesimal warna dan nilai alfa, seperti yang ditunjukkan dalam contoh berikut.
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );

Mode alfa

Terlepas dari mode alfa target render tempat Anda menggunakan kuas, nilai D2D1_COLOR_F selalu ditafsirkan sebagai alfa lurus.

Menggunakan kuas warna solid

Untuk membuat kuas warna solid, panggil metode ID2D1RenderTarget::CreateSolidColorBrush , yang mengembalikan HRESULT dan objek ID2D1SolidColorBrush . Ilustrasi berikut menunjukkan persegi yang dikatai dengan kuas warna hitam dan dicat dengan kuas warna solid yang memiliki nilai warna 0x9ACD32.

ilustrasi persegi dicat dengan kuas warna solid

Kode berikut menunjukkan cara membuat dan menggunakan kuas warna hitam dan kuas dengan nilai warna 0x9ACD32 untuk mengisi dan menggambar persegi ini.

    ID2D1SolidColorBrush *m_pBlackBrush;
    ID2D1SolidColorBrush *m_pYellowGreenBrush;
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
        &m_pBlackBrush
        );
}

// Create a solid color brush with its rgb value 0x9ACD32.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );
}
m_pRenderTarget->FillRectangle(&rcBrushRect, m_pYellowGreenBrush);
m_pRenderTarget->DrawRectangle(&rcBrushRect, m_pBlackBrush, 1, NULL);

Tidak seperti kuas lain, membuat ID2D1SolidColorBrush adalah operasi yang relatif murah. Anda dapat membuat objek ID2D1SolidColorBrush setiap kali Anda merender dengan sedikit atau tanpa dampak performa. Pendekatan ini tidak disarankan untuk kuas gradien atau bitmap.

Menggunakan kuas gradien linier

ID2D1LinearGradientBrush melukis area dengan gradien linier yang ditentukan di sepanjang garis, sumbu gradien. Anda menentukan warna gradien dan lokasinya di sepanjang sumbu gradien menggunakan objek ID2D1GradientStop . Anda juga dapat memodifikasi sumbu gradien, yang memungkinkan Anda membuat gradien horizontal dan vertikal dan membalikkan arah gradien. Untuk membuat kuas gradien linier, panggil metode ID2D1RenderTarget::CreateLinearGradientBrush .

Ilustrasi berikut menunjukkan persegi yang dicat dengan ID2D1LinearGradientBrush yang memiliki dua warna yang telah ditentukan sebelumnya, "Kuning" dan "ForestGreen".

ilustrasi persegi dicat dengan sikat gradien linier kuning dan hijau hutan

Untuk membuat gradien yang ditampilkan dalam ilustrasi sebelumnya, selesaikan langkah-langkah berikut:

  1. Deklarasikan dua objek D2D1_GRADIENT_STOP . Setiap stop gradien menentukan warna dan posisi. Posisi 0,0 menunjukkan awal gradien, sementara posisi 1,0 menunjukkan akhir gradien.

    Kode berikut membuat array dari dua objek D2D1_GRADIENT_STOP . Stop pertama menentukan warna "Kuning" pada posisi 0, dan stop kedua menentukan warna "ForestGreen" pada posisi 1.

    // Create an array of gradient stops to put in the gradient stop
    // collection that will be used in the gradient brush.
    ID2D1GradientStopCollection *pGradientStops = NULL;

    D2D1_GRADIENT_STOP gradientStops[2];
    gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
    gradientStops[0].position = 0.0f;
    gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
    gradientStops[1].position = 1.0f;
  1. Buat ID2D1GradientStopCollection. Contoh berikut memanggil CreateGradientStopCollection, meneruskan array objek D2D1_GRADIENT_STOP , jumlah pemberhentian gradien (2), D2D1_GAMMA_2_2 untuk interpolasi, dan D2D1_EXTEND_MODE_CLAMP untuk mode perluas.
    // Create the ID2D1GradientStopCollection from a previously
    // declared array of D2D1_GRADIENT_STOP structs.
    hr = m_pRenderTarget->CreateGradientStopCollection(
        gradientStops,
        2,
        D2D1_GAMMA_2_2,
        D2D1_EXTEND_MODE_CLAMP,
        &pGradientStops
        );
  1. Buat ID2D1LinearGradientBrush. Contoh berikutnya memanggil metode CreateLinearGradientBrush dan meneruskannya properti kuas gradien linier yang berisi titik awal pada (0, 0) dan titik akhir di (150, 150), dan gradien berhenti dibuat pada langkah sebelumnya.
    // The line that determines the direction of the gradient starts at
    // the upper-left corner of the square and ends at the lower-right corner.

    if (SUCCEEDED(hr))
    {
        hr = m_pRenderTarget->CreateLinearGradientBrush(
            D2D1::LinearGradientBrushProperties(
                D2D1::Point2F(0, 0),
                D2D1::Point2F(150, 150)),
            pGradientStops,
            &m_pLinearGradientBrush
            );
    }
  1. Gunakan ID2D1LinearGradientBrush. Contoh kode berikutnya menggunakan kuas untuk mengisi persegi panjang.
    m_pRenderTarget->FillRectangle(&rcBrushRect, m_pLinearGradientBrush);

Selengkapnya tentang perhentian gradien

D2D1_GRADIENT_STOP adalah blok penyusun dasar dari sikat gradien. Stop gradien menentukan warna dan posisi di sepanjang sumbu gradien. Nilai posisi gradien berkisar antara 0,0 dan 1,0. Semakin dekat ke 0,0, semakin dekat warnanya dengan awal gradien; semakin dekat ke 1,0, semakin dekat warnanya ke akhir gradien.

Ilustrasi berikut menyoroti pemberhentian gradien. Lingkaran menandai posisi pemberhentian gradien dan garis putus-putus memperlihatkan sumbu gradien.

ilustrasi kuas gradien linier dengan empat titik di sepanjang sumbu

Pemberhentian gradien pertama menentukan warna kuning pada posisi 0,0. Pemberhentian gradien kedua menentukan warna merah pada posisi 0,25. Dari kiri ke kanan sepanjang sumbu gradien, warna di antara kedua pemberhentian ini secara bertahap berubah dari kuning ke merah. Pemberhentian gradien ketiga menentukan warna biru pada posisi 0,75. Warna antara gradien kedua dan ketiga berhenti secara bertahap berubah dari merah ke biru. Pemberhentian gradien keempat menentukan hijau kapur pada posisi 1,0. Warna antara gradien ketiga dan keempat berhenti secara bertahap berubah dari biru ke hijau kapur.

Sumbu gradien

Seperti disebutkan sebelumnya, pemberhentian gradien dari sikat gradien linier diposisikan di sepanjang garis, sumbu gradien. Anda dapat menentukan orientasi dan ukuran garis menggunakan bidang startPoint dan endPoint dari struktur D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES saat Anda membuat sikat gradien linier. Setelah membuat kuas, Anda dapat menyesuaikan sumbu gradien dengan memanggil metode SetStartPoint dan SetEndPoint kuas. Dengan memanipulasi titik awal dan titik akhir kuas, Anda dapat membuat gradien horizontal dan vertikal, membalikkan arah gradien, dan banyak lagi.

Misalnya, dalam ilustrasi berikut, titik awal diatur ke (0,0) dan titik akhir ke (150, 50); ini menciptakan gradien diagonal yang dimulai di sudut kiri atas dan meluas ke sudut kanan bawah area yang dicat. Saat Anda mengatur titik awal ke (0, 25) dan titik akhir ke (150, 25), gradien horizontal dibuat. Demikian pula, mengatur titik awal ke (75, 0) dan titik akhir ke (75, 50) membuat gradien vertikal. Mengatur titik awal ke (0, 50) dan titik akhir ke (150, 0) membuat gradien diagonal yang dimulai di sudut kiri bawah dan meluas ke sudut kanan atas area yang dicat.

ilustrasi empat sumbu gradien yang berbeda di seluruh persegi panjang yang sama

Menggunakan kuas gradien radial

Tidak seperti ID2D1LinearGradientBrush, yang memadukan dua warna atau lebih di sepanjang sumbu gradien, ID2D1RadialGradientBrush melukis area dengan gradien radial yang memadukan dua warna atau lebih di seluruh elips. Sementara ID2D1LinearGradientBrush mendefinisikan sumbu gradiennya dengan titik awal dan titik akhir, ID2D1RadialGradientBrush mendefinisikan elips gradiennya dengan menentukan pusat, radii horizontal dan vertikal, dan offset asal gradien.

Seperti ID2D1LinearGradientBrush, ID2D1RadialGradientBrush menggunakan ID2D1GradientStopCollection untuk menentukan warna dan posisi dalam gradien.

Ilustrasi berikut menunjukkan lingkaran yang dicat dengan ID2D1RadialGradientBrush. Lingkaran memiliki dua pemberhentian gradien: yang pertama menentukan warna "Kuning" yang telah ditentukan sebelumnya pada posisi 0,0, dan yang kedua menentukan warna "ForestGreen" yang telah ditentukan sebelumnya pada posisi 1,0. Gradien memiliki pusat (75, 75), offset asal gradien (0, 0), dan radius x dan y 75.

ilustrasi lingkaran dicat dengan sikat gradien radial

Contoh kode berikut menunjukkan cara melukis lingkaran ini dengan ID2D1RadialGradientBrush yang memiliki dua perhentian warna: "Kuning" pada posisi 0,0, dan "ForestGreen" pada posisi 1,0. Mirip dengan membuat ID2D1LinearGradientBrush, contohnya memanggil CreateGradientStopCollection untuk membuat ID2D1GradientStopCollection dari array pemberhentian gradien.

// Create an array of gradient stops to put in the gradient stop
// collection that will be used in the gradient brush.
ID2D1GradientStopCollection *pGradientStops = NULL;

D2D1_GRADIENT_STOP gradientStops[2];
gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow, 1);
gradientStops[0].position = 0.0f;
gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::ForestGreen, 1);
gradientStops[1].position = 1.0f;
// Create the ID2D1GradientStopCollection from a previously
// declared array of D2D1_GRADIENT_STOP structs.
hr = m_pRenderTarget->CreateGradientStopCollection(
    gradientStops,
    2,
    D2D1_GAMMA_2_2,
    D2D1_EXTEND_MODE_CLAMP,
    &pGradientStops
    );

Untuk membuat METODE ID2D1RadialGradientBrush, gunakan metode ID2D1RenderTarget::CreateRadialGradientBrush . CreateRadialGradientBrush mengambil tiga parameter. Parameter pertama, D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES menentukan pusat, offset asal gradien, dan radii horizontal dan vertikal gradien. Parameter kedua adalah ID2D1GradientStopCollection yang menjelaskan warna dan posisinya dalam gradien, dan parameter ketiga adalah alamat penunjuk yang menerima referensi ID2D1RadialGradientBrush baru. Beberapa kelebihan beban mengambil parameter tambahan, struktur D2D1_BRUSH_PROPERTIES yang menentukan nilai opasitas dan transformasi untuk diterapkan ke kuas baru.

Contoh berikutnya memanggil CreateRadialGradientBrush, melewati array pemberhentian gradien, dan properti sikat gradien radial yang memiliki nilai tengah diatur ke (75, 75), gradientOriginOffset diatur ke (0, 0), dan radiusX dan radiusY keduanya diatur ke 75.

// The center of the gradient is in the center of the box.
// The gradient origin offset was set to zero(0, 0) or center in this case.
if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateRadialGradientBrush(
        D2D1::RadialGradientBrushProperties(
            D2D1::Point2F(75, 75),
            D2D1::Point2F(0, 0),
            75,
            75),
        pGradientStops,
        &m_pRadialGradientBrush
        );
}

Contoh terakhir menggunakan kuas untuk mengisi elips.

m_pRenderTarget->FillEllipse(ellipse, m_pRadialGradientBrush);
m_pRenderTarget->DrawEllipse(ellipse, m_pBlackBrush, 1, NULL);

Mengonfigurasi gradien radial

Nilai yang berbeda untuk pusat, gradienOriginOffset, radiusX dan/atau radiusY menghasilkan gradien yang berbeda. Ilustrasi berikut menunjukkan beberapa gradien radial yang memiliki offset asal gradien yang berbeda, menciptakan tampilan cahaya yang menerangi lingkaran dari sudut yang berbeda.

ilustrasi lingkaran yang sama dicat dengan sikat gradien radial dengan offset asal yang berbeda

Menggunakan kuas bitmap

ID2D1BitmapBrush melukis area dengan bitmap (diwakili oleh objek ID2D1Bitmap).

Ilustrasi berikut menunjukkan persegi dicat dengan bitmap tanaman.

ilustrasi persegi dicat dengan bitmap tanaman

Contoh yang mengikuti menunjukkan cara melukis persegi ini dengan ID2D1BitmapBrush.

Contoh pertama menginisialisasi ID2D1Bitmap untuk digunakan dengan kuas. ID2D1Bitmap disediakan oleh metode pembantu, LoadResourceBitmap, yang ditentukan di tempat lain dalam sampel.

// Create the bitmap to be used by the bitmap brush.
if (SUCCEEDED(hr))
{
    hr = LoadResourceBitmap(
        m_pRenderTarget,
        m_pWICFactory,
        L"FERN",
        L"Image",
        &m_pBitmap
        );
}

Untuk membuat kuas bitmap, panggil metode ID2D1RenderTarget::CreateBitmapBrush dan tentukan ID2D1Bitmap yang akan dicat. Metode mengembalikan HRESULT dan objek ID2D1BitmapBrush . Beberapa kelebihan beban CreateBitmapBrush memungkinkan Anda menentukan opsi tambahan dengan menerima D2D1_BRUSH_PROPERTIES dan struktur D2D1_BITMAP_BRUSH_PROPERTIES .

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

Contoh berikutnya menggunakan kuas untuk mengisi persegi panjang.

m_pRenderTarget->FillRectangle(&rcBrushRect, m_pBitmapBrush);

Mengonfigurasi mode perluasan

Terkadang, gradien sikat gradien atau bitmap untuk kuas bitmap tidak sepenuhnya mengisi area yang dicat.

Ilustrasi berikut menunjukkan hasil dari setiap kemungkinan kombinasi mode perluasan untuk ID2D1BitmapBrush: D2D1_EXTEND_MODE_CLAMP (CLAMP), D2D1_EXTEND_MODE_WRAP (WRAP), dan D2D1_EXTEND_MIRROR (MIRROR).

ilustrasi gambar asli dan gambar yang dihasilkan dari berbagai mode perluasan

Contoh berikut menunjukkan cara mengatur mode x- dan y-extend kuas bitmap ke D2D1_EXTEND_MIRROR. Kemudian melukis persegi panjang dengan ID2D1BitmapBrush.

m_pBitmapBrush->SetExtendModeX(D2D1_EXTEND_MODE_MIRROR);
m_pBitmapBrush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR);

m_pRenderTarget->FillRectangle(exampleRectangle, m_pBitmapBrush);

Ini menghasilkan output seperti yang ditunjukkan dalam ilustrasi berikut.

ilustrasi gambar asli dan gambar yang dihasilkan setelah mencerminkan arah x dan arah y

Mengubah kuas

Ketika Anda melukis dengan kuas, itu melukis di ruang koordinat target render. Kuas tidak secara otomatis memposisikan diri untuk menyelaraskan dengan objek yang dicat; secara default, mereka mulai melukis di asal (0, 0) dari target render.

Anda dapat "memindahkan" gradien yang ditentukan oleh ID2D1LinearGradientBrush ke area target dengan mengatur titik awal dan titik akhirnya. Demikian juga, Anda dapat memindahkan gradien yang ditentukan oleh ID2D1RadialGradientBrush dengan mengubah tengah dan radiinya.

Untuk menyelaraskan konten ID2D1BitmapBrush ke area yang dicat, Anda dapat menggunakan metode SetTransform untuk menerjemahkan bitmap ke lokasi yang diinginkan. Transformasi ini hanya mempengaruhi kuas; ini tidak memengaruhi konten lain yang digambar oleh target render.

Ilustrasi berikut menunjukkan efek menggunakan ID2D1BitmapBrush untuk mengisi persegi panjang yang terletak di (100, 100). Ilustrasi di ilustrasi kiri menunjukkan hasil mengisi persegi panjang tanpa mengubah kuas: bitmap digambar pada asal target render. Akibatnya, hanya sebagian bitmap yang muncul di persegi panjang. Ilustrasi di sebelah kanan menunjukkan hasil transformasi ID2D1BitmapBrush sehingga kontennya digeser 50 piksel ke kanan dan 50 piksel ke bawah. Bitmap sekarang mengisi persegi panjang.

ilustrasi persegi dicat dengan kuas bitmap tanpa mengubah kuas dan dengan mengubah kuas

Kode berikut menunjukkan cara mencapai hal ini. Pertama terapkan terjemahan ke ID2D1BitmapBrush, pindahkan kuas 50 piksel ke kanan di sepanjang sumbu x dan 50 piksel di sepanjang sumbu y. Kemudian gunakan ID2D1BitmapBrush untuk mengisi persegi panjang yang memiliki sudut kiri atas di (100, 100) dan sudut kanan bawah di (200, 200).

// Create the bitmap to be used by the bitmap brush.
if (SUCCEEDED(hr))
{
    hr = LoadResourceBitmap(
        m_pRenderTarget,
        m_pWICFactory,
        L"FERN",
        L"Image",
        &m_pBitmap
        );
   
}

if (SUCCEEDED(hr))
{
    hr = m_pRenderTarget->CreateBitmapBrush(
        m_pBitmap,
        &m_pBitmapBrush
        );
}

D2D1_RECT_F rcTransformedBrushRect = D2D1::RectF(100, 100, 200, 200);

// Demonstrate the effect of transforming a bitmap brush.
m_pBitmapBrush->SetTransform(
     D2D1::Matrix3x2F::Translation(D2D1::SizeF(50,50))
     );

// To see the content of the rcTransformedBrushRect, comment
// out this statement.
m_pRenderTarget->FillRectangle(
     &rcTransformedBrushRect, 
     m_pBitmapBrush
     );

m_pRenderTarget->DrawRectangle(rcTransformedBrushRect, m_pBlackBrush, 1, NULL);