Partager via


Présentation des pinceaux

Cette vue d’ensemble explique comment créer et utiliser des objets ID2D1SolidColorBrush, ID2D1LinearGradientBrush, ID2D1RadialGradientBrush et ID2D1BitmapBrush pour peindre des zones avec des couleurs solides, des dégradés et des bitmaps. Elle contient les sections suivantes.

Conditions préalables

Cette vue d’ensemble suppose que vous connaissez la structure d’une application Direct2D de base, comme décrit dans Créer une application Direct2D simple.

Types de pinceau

Un pinceau « peint » une zone avec sa sortie. Différents pinceaux ont différents types de sortie. Direct2D fournit quatre types de pinceaus : ID2D1SolidColorBrush peint une zone avec une couleur unie, ID2D1LinearGradientBrush avec un dégradé linéaire, ID2D1RadialGradientBrush avec un dégradé radial et ID2D1BitmapBrush avec une bitmap.

Remarque

À compter de Windows 8, vous pouvez également utiliser ID2D1ImageBrush, qui est similaire à un pinceau bitmap, mais vous pouvez également utiliser des primitives.

Tous les pinceaux héritent d’ID2D1Brush et partagent un ensemble de fonctionnalités communes (définition et obtention d’opacité et transformation de pinceaux) ; ils sont créés par ID2D1RenderTarget et sont des ressources dépendantes de l’appareil : votre application doit créer des pinceaux après qu’elle initialise la cible de rendu avec laquelle les pinceaux seront utilisés et recréez les pinceaux chaque fois que la cible de rendu a besoin de recréer. (Pour plus d’informations sur les ressources, consultez Vue d’ensemble des ressources.)

L’illustration suivante montre des exemples de chacun des différents types de pinceau.

illustration des effets visuels des pinceaux de couleur unie, des pinceaux de dégradé linéaire, des pinceaux de dégradé radial et des pinceaux bitmap

Principes de base des couleurs

Avant de peindre avec un pinceau ID2D1SolidColorBrush ou un pinceau à dégradé, vous devez choisir des couleurs. Dans Direct2D, les couleurs sont représentées par la structure D2D1_COLOR_F (qui n’est en fait qu’un nouveau nom pour la structure utilisée par Direct3D, D3DCOLORVALUE).

Avant Windows 8, D2D1_COLOR_F utilise l’encodage sRGB. L’encodage sRGB divise les couleurs en quatre composants : rouge, vert, bleu et alpha. Chaque composant est représenté par une valeur à virgule flottante avec une plage normale de 0,0 à 1,0. La valeur 0.0 indique l’absence complète de cette couleur, tandis qu’une valeur de 1,0 indique que la couleur est entièrement présente. Pour le composant alpha, 0.0 représente une couleur entièrement transparente et 1.0 représente une couleur entièrement opaque.

À compter de Windows 8, D2D1_COLOR_F accepte également l’encodage scRGB. scRVB est un sur-ensemble qui autorise les valeurs de couleur supérieures à 1,0 et inférieures à 0,0.

Pour définir une couleur, vous pouvez utiliser la structure D2D1_COLOR_F et initialiser vos champs vous-même, ou vous pouvez utiliser la classe D2D1 ::ColorF pour vous aider à créer la couleur. La classe ColorF fournit plusieurs constructeurs pour définir des couleurs. Si la valeur alpha n’est pas spécifiée dans les constructeurs, la valeur par défaut est 1.0.

  • Utilisez le constructeur ColorF(Enum, FLOAT) pour spécifier une couleur prédéfinie et une valeur de canal alpha. Une valeur de canal alpha varie de 0,0 à 1.0, où 0.0 représente une couleur entièrement transparente et 1.0 représente une couleur entièrement opaque. L’illustration suivante montre plusieurs couleurs prédéfinies et leurs équivalents hexadécimaux. Pour obtenir la liste complète des couleurs prédéfinies, consultez la section Constantes Color de la classe ColorF .

    illustration de couleurs prédéfinies

    L’exemple suivant crée une couleur prédéfinie et l’utilise pour spécifier la couleur d’un ID2D1SolidColorBrush.

hr = m_pRenderTarget->CreateSolidColorBrush(
    D2D1::ColorF(D2D1::ColorF::Black, 1.0f),
    &m_pBlackBrush
    );
  • Utilisez le constructeur ColorF(FLOAT, FLOAT, FLOAT) pour spécifier une couleur dans la séquence d’un rouge, vert, bleu et alpha, où chaque élément a une valeur comprise entre 0,0 et 1.0.

    L’exemple suivant spécifie les valeurs rouge, verte, bleue et alpha d’une couleur.

    ID2D1SolidColorBrush *pGridBrush = NULL;
    hr = pCompatibleRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0.93f, 0.94f, 0.96f, 1.0f)),
        &pGridBrush
        );
  • Utilisez le constructeur ColorF(UINT32, FLOAT) pour spécifier la valeur hexadécimale d’une couleur et une valeur alpha, comme illustré dans l’exemple suivant.
    hr = m_pRenderTarget->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)),  
        &m_pYellowGreenBrush
        );

Modes alpha

Quel que soit le mode alpha de la cible de rendu avec laquelle vous utilisez un pinceau, D2D1_COLOR_F valeurs sont toujours interprétées comme alpha droites.

Utilisation de pinceaux de couleur unie

Pour créer un pinceau de couleur unie, appelez la méthode ID2D1RenderTarget ::CreateSolidColorBrush , qui retourne un HRESULT et un objet ID2D1SolidColorBrush . L'illustration suivante montre un carré tracé au pinceau de couleur noire et peint avec un pinceau de couleur unie, de couleur 0x9ACD32.

illustration d’un carré peint avec un pinceau de couleur unie

Le code suivant montre comment créer et utiliser un pinceau de couleur noire et un pinceau avec une valeur de couleur de 0x9ACD32 pour remplir et dessiner ce carré.

    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);

Contrairement à d’autres pinceaux, la création d’un ID2D1SolidColorBrush est une opération relativement peu coûteuse. Vous pouvez créer des objets ID2D1SolidColorBrush chaque fois que vous effectuez un rendu sans impact sur les performances. Cette approche n’est pas recommandée pour les pinceaux dégradés ou binarisés.

Utilisation de pinceaux de dégradé linéaire

Un id2D1LinearGradientBrush peint une zone avec un dégradé linéaire défini le long d’une ligne, l’axe du dégradé. Vous spécifiez les couleurs du dégradé et leur emplacement le long de l’axe de dégradé à l’aide d’objets ID2D1GradientStop . Vous pouvez également modifier l’axe de dégradé, ce qui vous permet de créer un dégradé horizontal et vertical et d’inverser la direction du dégradé. Pour créer un pinceau de dégradé linéaire, appelez la méthode ID2D1RenderTarget ::CreateLinearGradientBrush .

L’illustration suivante montre un carré peint avec un ID2D1LinearGradientBrush qui a deux couleurs prédéfinies, « Jaune » et « ForestGreen ».

Illustration d’un carré peint avec un pinceau à dégradé linéaire de jaune et de vert forêt

Pour créer le dégradé illustré dans l’illustration précédente, procédez comme suit :

  1. Déclarez deux objets D2D1_GRADIENT_STOP. Chaque point de dégradé spécifie une couleur et une position. Une position de 0,0 indique le début du dégradé, tandis qu’une position de 1,0 indique la fin du dégradé.

    Le code suivant crée un tableau de deux objets D2D1_GRADIENT_STOP . Le premier arrêt spécifie la couleur « Jaune » à la position 0, et le deuxième arrêt spécifie la couleur « ForestGreen » à la position 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. Créez un objet ID2D1GradientStopCollection. L’exemple suivant appelle CreateGradientStopCollection, en passant le tableau d’objets D2D1_GRADIENT_STOP , le nombre d’arrêts de dégradé (2), D2D1_GAMMA_2_2 pour l’interpolation et D2D1_EXTEND_MODE_CLAMP pour le mode d’extension.
    // 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. Créez l’ID2D1LinearGradientBrush. L’exemple suivant appelle la méthode CreateLinearGradientBrush et lui transmet les propriétés du pinceau à dégradé linéaire qui contiennent le point de départ à (0, 0) et le point de fin à (150, 150), ainsi que les arrêts de dégradé créés à l’étape précédente.
    // 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. Utilisez ID2D1LinearGradientBrush. L’exemple de code suivant utilise le pinceau pour remplir un rectangle.
    m_pRenderTarget->FillRectangle(&rcBrushRect, m_pLinearGradientBrush);

Plus d'informations sur les points de dégradé

Le D2D1_GRADIENT_STOP est le composant de base d’un pinceau de dégradé. Un point de dégradé spécifie la couleur et la position le long de l’axe de dégradé. La valeur de la position de dégradé est comprise entre 0,0 et 1,0. Plus elle est proche de 0,0, plus la couleur est proche du début du dégradé ; plus elle est proche de 1,0, plus la couleur est proche de la fin du dégradé.

Les points de dégradé sont mis en évidence sur l'illustration suivante. Les cercles indiquent les emplacements des points de dégradé et une ligne en pointillés montre l’axe du dégradé.

illustration d’un pinceau de dégradé linéaire avec quatre arrêts le long de l’axe

Le premier point de dégradé spécifie la couleur jaune à une position de 0,0. Le deuxième point de dégradé spécifie la couleur rouge à une position de 0,25. De gauche à droite le long de l’axe dégradé, les couleurs entre ces deux arrêts passent progressivement du jaune au rouge. Le troisième point de dégradé spécifie la couleur bleue à une position de 0,75. Les couleurs situées entre le deuxième et le troisième point de dégradé passent progressivement du rouge au bleu. Le quatrième point de dégradé spécifie la couleur vert citron à une position de 1,0. Les couleurs entre le troisième et le quatrième arrêt du dégradé changent progressivement du bleu au vert citron.

Axe de dégradé

Comme mentionné précédemment, les points de dégradé d'une brosse à dégradé linéaire sont disposés le long d'une ligne, sur l'axe du dégradé. Vous pouvez spécifier l’orientation et la taille de la ligne à l’aide des champs startPoint et endPoint de la structure D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lorsque vous créez un pinceau de dégradé linéaire. Une fois que vous avez créé un pinceau, vous pouvez ajuster l’axe de dégradé en appelant les méthodes SetStartPoint et SetEndPoint du pinceau. En manipulant le point de départ et le point de terminaison du pinceau, vous pouvez créer des dégradés horizontaux et verticaux, inverser la direction du dégradé, etc.

Par exemple, dans l’illustration suivante, le point de départ est défini sur (0,0) et le point de terminaison sur (150, 50) ; cela crée un dégradé diagonal qui commence à l’angle supérieur gauche et s’étend au coin inférieur droit de la zone peinte. Lorsque vous définissez le point de départ sur (0, 25) et le point de terminaison sur (150, 25), un dégradé horizontal est créé. De même, définir le point de départ sur (75, 0) et le point de terminaison sur (75, 50) crée un dégradé vertical. La définition du point de départ sur (0, 50) et le point de fin sur (150, 0) crée un dégradé diagonal qui commence au coin inférieur gauche et s’étend au coin supérieur droit de la zone peinte.

illustration de quatre axes de dégradé différents sur le même rectangle

Utilisation de pinceaux de dégradés radiaux

Contrairement à un ID2D1LinearGradientBrush, qui fusionne deux couleurs ou plus le long d’un axe de dégradé, un id2D1RadialGradientBrush peint une zone avec un dégradé radial qui fusionne deux couleurs ou plus sur un ellipse. Alors qu’un ID2D1LinearGradientBrush définit son axe de dégradé avec un point de départ et un point de terminaison, un ID2D1RadialGradientBrush définit son ellipse dégradé en spécifiant un rayon central, horizontal et vertical et un décalage d’origine dégradée.

Comme un ID2D1LinearGradientBrush, un ID2D1RadialGradientBrush utilise un ID2D1GradientStopCollection pour spécifier les couleurs et les positions dans le dégradé.

L’illustration suivante montre un cercle peint avec un ID2D1RadialGradientBrush. Le cercle a deux arrêts de dégradé : le premier spécifie une couleur prédéfinie « Jaune » à une position de 0,0, et la seconde spécifie une couleur prédéfinie « ForestGreen » à une position de 1,0. Le dégradé a un centre de (75, 75), un décalage d’origine de dégradé de (0, 0) et un rayon x et y de 75.

illustration d’un cercle peint avec un pinceau dégradé radial

Les exemples de code suivants montrent comment peindre ce cercle avec un ID2D1RadialGradientBrush qui a deux taquets de couleur : « Jaune » à une position de 0,0 et « ForestGreen » à la position 1.0. Comme pour créer un ID2D1LinearGradientBrush, l’exemple appelle CreateGradientStopCollection pour créer un ID2D1GradientStopCollection à partir d’un tableau d’arrêts de dégradé.

// 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
    );

Pour créer un ID2D1RadialGradientBrush, utilisez la méthode ID2D1RenderTarget ::CreateRadialGradientBrush . CreateRadialGradientBrush prend trois paramètres. Le premier paramètre, un D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES spécifie le centre, le décalage d’origine du dégradé et le rayon horizontal et vertical du dégradé. Le deuxième paramètre est un ID2D1GradientStopCollection qui décrit les couleurs et leurs positions dans le dégradé, et le troisième paramètre est l’adresse du pointeur qui reçoit la nouvelle référence ID2D1RadialGradientBrush . Certaines surcharges prennent un paramètre supplémentaire, une structure D2D1_BRUSH_PROPERTIES qui spécifie une valeur d’opacité et une transformation à appliquer au nouveau pinceau.

L’exemple suivant appelle CreateRadialGradientBrush, en passant le tableau d’arrêts de dégradé et les propriétés de pinceau de dégradé radial qui ont la valeur centrale définie sur (75, 75), le gradientOriginOffset défini sur (0, 0) et radiusX et radiusY définis sur 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
        );
}

L’exemple final utilise le pinceau pour remplir un ellipse.

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

Configuration d’un dégradé radial

Différentes valeurs pour le centre, gradientOriginOffset, radiusX et/ou radiusY produisent différents dégradés. L’illustration suivante montre plusieurs dégradés radial qui ont des décalages d’origine de dégradé différents, créant ainsi l’apparence de la lumière éclairant les cercles de différents angles.

Illustration du même cercle peint avec des pinceaux à dégradé radial avec des décalages d’origine différents

Utilisation de pinceaux bitmap

Un id2D1BitmapBrush peint une zone avec une bitmap (représentée par un objet ID2D1Bitmap ).

L’illustration suivante montre un carré peint avec une bitmap d’une plante.

illustration d’un carré peint avec une image bitmap de plante

Les exemples suivants montrent comment peindre ce carré avec un id2D1BitmapBrush.

Le premier exemple initialise un ID2D1Bitmap à utiliser avec le pinceau. L’ID2D1Bitmap est fourni par une méthode d’assistance, LoadResourceBitmap, définie ailleurs dans l’exemple.

// 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
        );
}

Pour créer le pinceau bitmap, appelez la méthode ID2D1RenderTarget ::CreateBitmapBrush et spécifiez l’ID2D1Bitmap avec lequel peindre. La méthode retourne un HRESULT et un objet ID2D1BitmapBrush . Certaines surcharges de CreateBitmapBrush vous permettent de spécifier des options supplémentaires en acceptant une structure D2D1_BRUSH_PROPERTIES et D2D1_BITMAP_BRUSH_PROPERTIES.

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

L’exemple suivant utilise le pinceau pour remplir un rectangle.

m_pRenderTarget->FillRectangle(&rcBrushRect, m_pBitmapBrush);

Configuration des modes d’extension

Parfois, le dégradé d’un pinceau dégradé ou l'image bitmap dans le cas d'un pinceau bitmap ne remplit pas complètement la zone en cours de peinture.

  • Lorsque cela se produit pour un id2D1BitmapBrush, Direct2D utilise les paramètres de mode d’extension horizontal (SetExtendModeX) et vertical (SetExtendModeY) du pinceau pour déterminer comment remplir la zone restante.

  • Lorsque cela se produit pour un pinceau dégradé, Direct2D détermine comment remplir la zone restante à l’aide de la valeur du paramètre D2D1_EXTEND_MODE que vous avez spécifié lorsque vous avez appelé CreateGradientStopCollection pour créer l’ID2D1GradientStopCollection du pinceau dégradé.

L’illustration suivante montre les résultats de chaque combinaison possible des modes d’extension d’un id2D1BitmapBrush : D2D1_EXTEND_MODE_CLAMP (CLAMP), D2D1_EXTEND_MODE_WRAP (WRAP) et D2D1_EXTEND_MIRROR (MIRROR).

illustration d’une image d’origine et des images résultantes de différents modes d’extension

L'exemple suivant montre comment définir les modes d'extension en x et y du pinceau bitmap sur D2D1_EXTEND_MIRROR. Il peint ensuite le rectangle avec l’ID2D1BitmapBrush.

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

m_pRenderTarget->FillRectangle(exampleRectangle, m_pBitmapBrush);

Cela produit un résultat comme indiqué dans l’illustration suivante.

illustration d’une image d’origine et de l’image résultante après la mise en miroir de la direction x et de la direction y

Transformation des pinceaux

Lorsque vous peintz avec un pinceau, il peint dans l’espace de coordonnées de la cible de rendu. Les pinceaux ne se positionnent pas automatiquement pour s’aligner sur l’objet peint ; par défaut, ils commencent à peindre à l’origine (0, 0) de la cible de rendu.

Vous pouvez « déplacer » le dégradé défini par un ID2D1LinearGradientBrush sur une zone cible en définissant son point de départ et son point de terminaison. De même, vous pouvez déplacer le dégradé défini par un ID2D1RadialGradientBrush en modifiant son centre et son rayon.

Pour aligner le contenu d’un ID2D1BitmapBrush sur la zone peinte, vous pouvez utiliser la méthode SetTransform pour traduire la bitmap à l’emplacement souhaité. Cette transformation affecte uniquement le pinceau ; elle n’affecte aucun autre contenu dessiné par la cible de rendu.

Les illustrations suivantes montrent l’effet de l’utilisation d’un ID2D1BitmapBrush pour remplir un rectangle situé à (100, 100). L’illustration de gauche montre le résultat du remplissage du rectangle sans transformer le pinceau : l’image bitmap est dessinée à l’origine de la cible de rendu. Par conséquent, seule une partie de la bitmap apparaît dans le rectangle. L’illustration à droite montre le résultat de la transformation de l’ID2D1BitmapBrush afin que son contenu soit décalé de 50 pixels vers la droite et de 50 pixels vers le bas. La bitmap remplit désormais le rectangle.

illustration d'un carré peint avec un pinceau bitmap, sans transformation du pinceau, et avec transformation du pinceau

Le code suivant montre comment effectuer cette opération. Tout d’abord, appliquez une traduction à l’ID2D1BitmapBrush, déplaçant le pinceau de 50 pixels le long de l’axe x et de 50 pixels le long de l’axe y. Utilisez ensuite l’ID2D1BitmapBrush pour remplir le rectangle qui a le coin supérieur gauche à (100, 100) et le coin inférieur droit à (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);