IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec C & C++ Discussion :

[Cairo] rectangle arrondi : border-radius et border-width


Sujet :

GTK+ avec C & C++

  1. #1
    Membre régulier Avatar de Persistant
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2016
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Septembre 2016
    Messages : 50
    Points : 73
    Points
    73
    Par défaut [Cairo] rectangle arrondi : border-radius et border-width
    Bonsoir à tous,

    Je souhaite dessiner les bords rouge de l'image ci-dessous en fonction des données CSS présente dans l'image avec les fonctions Cairo.
    Nom : cairo-border-red.png
Affichages : 239
Taille : 7,6 Ko


    Comment vous y prendriez-vous ?

    PS: Le site de cairographics m'a donné une première piste pour dessiner des rectangle arrondi mais ca reste insuffisant car je souhaite utiliser des border-style:inset ce qui pose problème quand je veux dessiner le background.

  2. #2
    Membre régulier Avatar de Persistant
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2016
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Septembre 2016
    Messages : 50
    Points : 73
    Points
    73
    Par défaut
    Petit retour pour ceux d'entre vous qui serrai éventuellement intéressé,

    Je vais utiliser la fonction cairo_fill au lieu de cairo_stroke pour dessiner les border. Comme dans cette exemple: fill_style

    J'ai crée cette fonction a l'instar de cairo_rectangle a la différence qu'elle gère les border en x et y pour chaque coin
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    struct _DevianceRadius {
        gdouble rx;
        gdouble ry;
    };
     
    struct _DevianceCorners {
        DevianceRadius top_left;
        DevianceRadius top_right;
        DevianceRadius bottom_right;
        DevianceRadius bottom_left;
    };
     
     
    void
    deviance_graphics_data_path_rectangle(cairo_t *cr,
                                          DevianceRectangle *rect,
                                          DevianceCorners *corners)
    {
        double x         = rect->x,
               y         = rect->y,
               width     = rect->width,
               height    = rect->height;
     
        cairo_new_sub_path (cr);
     
        if (0.0==corners->top_left.rx || 0.0==corners->top_left.ry) {
            cairo_move_to(cr, x, y);
        } else {
            cairo_move_to(cr, x+corners->top_left.rx, y);
        }
     
        if (0.0==corners->top_right.rx || 0.0==corners->top_right.ry) {
            cairo_line_to(cr, x+width, y);
        } else {
            cairo_line_to(cr, x+width-corners->top_right.rx, y);
            cairo_curve_to(cr,
                           x+width-corners->top_right.rx*0.44771525016, y,
                           x+width, y+corners->top_right.ry*0.44771525016,
                           x+width, y+corners->top_right.ry);
        }
     
        if (0.0==corners->bottom_right.rx || 0.0==corners->bottom_right.ry) {
            cairo_line_to(cr, x+width, y+height);
        } else {
            cairo_line_to(cr, x+width, y+height-corners->bottom_right.ry);
            cairo_curve_to(cr,
                           x+width, y+height-corners->bottom_right.ry*0.44771525016,
                           x+width-corners->bottom_right.rx*0.44771525016, y+height,
                           x+width-corners->bottom_right.rx, y+height);
        }
     
        if (0.0==corners->bottom_left.rx || 0.0==corners->bottom_left.ry) {
            cairo_line_to(cr, x+corners->bottom_left.rx, y+height);
        } else {
            cairo_line_to(cr, x+corners->bottom_left.rx, y+height);
            cairo_curve_to(cr,
                           x+corners->bottom_left.rx*0.44771525016, y+height,
                           x, y+height-corners->bottom_left.ry*0.44771525016,
                           x, y+height-corners->bottom_left.ry);
        }
     
     
        if (0.0==corners->top_left.rx || 0.0==corners->top_left.ry) {
            cairo_line_to(cr, x, y);
        } else {
            cairo_line_to(cr, x, y+corners->top_left.ry);
            cairo_curve_to(cr,
                           x, y+corners->top_left.ry*0.44771525016,
                           x+corners->top_left.rx*0.44771525016, y,
                           x+corners->top_left.rx, y);
        }
     
    }
     
    // @see: <a href="http://stackoverflow.com/questions/1734745/how-to-create-circle-with-b%C3%A9zier-curves" target="_blank">http://stackoverflow.com/questions/1...%A9zier-curves</a>
    // @note: 0.44771525016 = 1-0.552284749831

    Utilisation:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        DevianceRectangle rect = {10.0, 10.0, 100, 41};
        DevianceCorners corners = {
            {12.0, 12.0}, {12.0, 12.0},
            {12.0, 12.0}, {12.0, 12.0},
        };
        deviance_graphics_data_path_rectangle(cr, &rect, &corners);
     
        gdouble border_width[4] = {1.0, 8.0, 1.0, 8.0};
        DevianceRectangle r = {rect.x+border_width[0], rect.y+border_width[1], rect.width-border_width[0]-border_width[2], rect.height-border_width[1]-border_width[3]};
        DevianceCorners c = {
            {12.0, 12.0}, {12.0, 12.0},
            {12.0, 12.0}, {12.0, 12.0},
        };
        deviance_graphics_data_path_rectangle(cr, &r, &c);
     
        cairo_close_path (cr);
        cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
        cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
        cairo_fill (cr);

    Résulat:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        DevianceCorners c = {
            {12.0, 12.0}, {12.0, 12.0},
            {12.0, 12.0}, {12.0, 12.0},
        };
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        DevianceCorners c = {
            {8.0, 4.0}, {8.0, 4.0},
            {8.0, 4.0}, {8.0, 4.0},
        };
    Nom : border-radius.png
Affichages : 223
Taille : 830 octets Nom : border-radius.png
Affichages : 182
Taille : 707 octets




    Bien à vous

  3. #3
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Points : 2 002
    Points
    2 002
    Par défaut
    Bonjour,

    je te conseille:
    1. d'utiliser des define pour tes constantes magiques
    2. de garder une api proche de cairo avec x, y, longueur, hauteur
    3. de ne jamais faire de comparaison stricte (==) en float ou double http://floating-point-gui.de/
    Documentation officielle GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels GTK+ 3:
    GTK en C, GTK en Python

    Tutoriels par l'exemple (platform-demos):
    GTK (tous langages)

  4. #4
    Membre régulier Avatar de Persistant
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2016
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Septembre 2016
    Messages : 50
    Points : 73
    Points
    73
    Par défaut
    Citation Envoyé par 2
    garder une api proche de cairo avec x, y, longueur, hauteur
    Je suis d'accord qu'il est préférable de conserver une certaine homogénéité dans les signatures des fonctions.
    Mais quand je le fais, je suis agacé par le nombre de paramètre

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
     * @usage
     * coria_rounded_rectangle(cr, 0.0, 0.0, 100.0, 50.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0); 
     */
    void
    coria_rounded_rectangle(cairo_t *cr,
                            gdouble x, gdouble y, gdouble width, gdouble height,
                            gdouble top_left_radius_x, gdouble top_left_radius_y,
                            gdouble top_right_radius_x, gdouble top_right_radius_y,
                            gdouble bottom_left_radius_x, gdouble bottom_left_radius_y,
                            gdouble bottom_right_radius_x, gdouble bottom_right_radius_y) {
    }
    Du coup, je vais me détacher de la couche "graphics" (cairo) et créer ou couche que je vais appeler "display" responsable de l'orchestration de cairo.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    static cairo_path_t*
    deviance_display_create_rounded_rectangle(DevianceRectangle *rect, DevianceCorners *corners) {
    }
    static void
    deviance_display_update_rounded_rectangle(cairo_path_t *path, DevianceRectangle *rect, DevianceCorners *corners) {
    }

    Pour le 3ème point, je vais utiliser une fonction gboolean deviance_display_is_epsilon(gdouble value) qui vérifia si la valeur est entre -0.01 et 0.01

  5. #5
    Membre régulier Avatar de Persistant
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Septembre 2016
    Messages
    50
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Septembre 2016
    Messages : 50
    Points : 73
    Points
    73
    Par défaut
    Je re-ouvre cette discution car ma fonction deviance_graphics_data_path_rectangle a trop de bug et j'avoue bugger quand a les résoudre.

    - Si les border sont trop large par rapport au rectangle ca bug
    - si le radius est trop grand par rapport a la tail du rectangle ca bug

    Si vous avez des solutions à me proposer je suis vraiment preneur...

Discussions similaires

  1. chrome border-radius image + border
    Par 5Seth dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 12/08/2012, 17h21
  2. Redimensionner un -moz-border-radius
    Par Storke dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 28/01/2010, 18h05
  3. "Border-radius" n'affiche rien
    Par roinho dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 20/12/2009, 17h28
  4. border-radius et IE7
    Par ALCINA dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 12/12/2007, 16h10
  5. Coins arrondis avec border-radius
    Par mullger dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 13/12/2006, 21h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo