Chapter 2. Ce qu'il y a derrière

Table of Contents
Le graphe de scène
Utilisation interne des MVC
Modules

Le graphe de scène

Le graphe de scène est détacher des objets de type corba Graphic. Nous décrirons ici quelques uns des problèmes d'implémentation les plus sanglantes des Graphic, ses sous-classes et ses collaborateurs.

Contenu structurel (pointeurs)

Structurellement, il y a un "pointeur" (une référence corba) de chaque parent graphics vers chacun de ses enfants, ainsi que de chaque enfant vers son(ses) parent(s). La raison pour la référence enfant vers parent est que, comme nous l'avons vu rapidement, le graphe de scène peut partager des enfants entres de multiples parents. Ces références sont utilisées par les traverses pour "parcourir" le graphe, réalisant plusieurs opérations sur la scène.

L'addition d'un enfant à un parent est aussi simple que d'appeler la méthode append() du parent, bien que il n'est pas évident de savoir exactemment où un parent placera l'enfant dans sa région. C'est en fait notre intention, puisque la mise en page dans le scène de graphe est dynamique et les spécificités de chaque processus de mise en page sont encapsulés dans un protocole de réservation simple que nous décrirons plus tard. Pour l'instant, il suffit de montrer les bases de la connection d'un enfant à un parent. Ici nous connectons un rectangle enfant à un boîte horizontale (un conténaire de mise en page transparent).

Example 2-1. Ajouter un enfant à un parent

  Graphic_var hbox = lk-hbox();
  Graphic_var rect = fk-rectangle(x,y,style);
  hbox-append(rect);

Détails des traverses

Comportement du visiteur

Les traverses utilisent une nouvelle forme de comportement de visite pour faire un changement de cast de façon sure et rapide d'un objet de traverse dans l'un des types de traverse presque inconnu. Plutôt que considérer la traverse comme un visiteur du noeud (et permettre au noeud de rappeler la traverse avec son type), nous considérons le noeud comme un visiteur de la traverse, et demandons à la traverse de rappeler le noeud avec le type de la traverse. C'est une decision importante, et elle doit bien être comprise pour suivre la séquence d'appel de la traverse. La décision de procéder ainsi a été prise parce qu'il existe relativement peu de types de traverse (deux, actuellement) alors qu'il existe un nombre illimité de types d'illustration.

Division des responsabilités

La responsabilité du séquencage du "parcour de l'arbre" par une traverse est partagé ente l'objet traverse lui-même et le noeud qu'il visite. Si le noeud est un noeud composite, tel qu'un PolyGraphic, alors il fera le séquencage individuellement la traverse à travers chacun de ses enfants dans l'ordre qui correspond au mieux à la manière qu'il a organisé ses enfants, spatiallement et logiquement.

Multiples interfaces

Si vous jetez un oeil sur l'image d'exemple ci-dessus, vous devez considèrer le graphe de scène adjacent comment une approximation brute de la structure de données la soulignant. Cela montre la manière dont vous étes supposé le représenter, mais ce n'est pas exactement comment les différentes parties du serveur la verront.

Vue de berlin / kit

Le serveur de berlin, et les kits qu'il charge,voient la scène comme un mélange d'objets C++ concrets et de références corba inconnu. Les objets C++ qui ont été créés par chaque instance d'un kit lui sont, en général, connu par leur types concrets. Par exemple, le LayoutKit connait le type d'implémentation spécifique RectImpl. Les clients ne connaissent rien sur ce type d'objet, ni sur un quelconque partie du serveur de berlin en dehors du LayoutKit. Lorsqu'un client appelle LayoutKit::rectangle(), une instance du LayoutKit répondra en créant un nouveau RectImpl et lui retournera une poignée. Le type de poignée qu'il retourne sera le type de référence corba opaque Graphic. Le kit maintiendra un pointeur C++ vers le RectImpl qu'il a construit, de telle manière qu'il puisse appeler delete avec le pointeur lorsque que le kit sera desallouer. Personne en dehors du kit n'a besoin de connaître le type d'implémentation concret. Ceci est particulièrement important pour les kits largement utilisés, puisqu'ils peuvent implémenter la mise ne commun de leur propre ressources et partager les méchanismes sans avoir besoin d'informer une quelconque partie du serveur.

Il arrive souvent de ne pas comprendre cela parce que les kits et le serveur peuvent uniquement connaître un seul autre objet par leurs types corba, ils doivent rassembler toutes leurs appels de méthode sur de tels objets à travers des sortes d'interfaces TCP "factice". Ce n'est pas complétement vrai ; si des objets sont co-positionnés dans le même processus, un appel vers une référence corba correspond simplement à l'appel d'une méthode virtuelle C++ normale et cela se passe aussi rapidement que n'importe quel autre.

Vue du client

Les clients d'autres processus voient uniquement la "vue corba" du graphe de scène, puisqu'ils obtienne toutes les références sur le graphe par corba. Les interfaces que nous exposons par l'intermédiaire de corba sont plus simple et moins nombreux que les objets d'implémentation dans les kits. L'unique partie exposée sont ceux qui sont strictement nécessaires à un client pour manipuler la structure du graphe. Par exemple, là où le FigureKit voit un RectImpl, ou le LayoutKit voit un QuadTree, le client verra juste 2 objets différents du type corba opaque "Graphic".

Aspect technique de l'affichage

Nous allons discuter ici des plusieurs services que l'interface de dessins de berlin supporte.

Coupure (clipping)

Dessiner dans un environnement fenêtré nécessite frequemment de couper les zones dessinées dans des régions spécifiques, telles que les chutes, qui tombent en dehors de la région, n'apparaissent pas sur le média final. Berlin supporte une pile de régions coupées, telles que les enfants peuvent ajouter des contraintes plus serrés, qui seront entrecoupées avec celles de n'importe quelles de leur parents qui ont été mis sur la pile de coupure.

Fonctions de dessins

Pour placer des pixels sur l'écran, une illustration peut demander qu'un chemin, un glyphe, ou un raster soit dessiné. De tels éléments visuels sont éclatés dans un composant stylistique et un composant compacte de modèle de données.

Chemins

Un chemin est une séquence de vecteurs, éventuellement accompagné par une séquence de scalaires spécifiant le vecteur noeud du chemin s'il représente un objet NURBS. Si le chemin n'a pas de vecteur noeud, il est interprété comme un polygone.

Glyphes

Un glyphe texte est acutellement un élément plutôt complexe, puisqu'il interagit avec ses gliphes voisins de manières non-traivialles. Ainsi, plutôt que d'essayer de faire un rendu des glyphes de manière uniforme en envoyant des bitmaps ou des courbes pour faciliter le dessin, nous déléguons toute la décision de la façon de faire le rendu d'une interface opaque qui peut avoir différentes implémentations fournies pour différents rendues finals, tels que les imprimantes ou des écrans basses résolutions. Nous fournissons des "morceaux" de texte unicode, arrêté à des intervalles où le standard spécifie qu'aucune interaction ne peut survenir, et demande au service de dessin de dessiner le texte à notre place (ainsi que de retourner l'espace occupée par le dessin, donc nous pouvons le représenter proprement).

Les rasters

Dans certains cas, il n'est pas approprié de dessiner avec des chemins de vecteurs. Dans ces cas-là, nous avons un service pour charger des rasters PNG dans le serveur d'affichage, et donc les affecter aux noeuds du graphe de scène. De tels reaffichages peuvent être fait de façon très efficace parce que le raster peut vivre dans le serveur d'affichage, et que c'est approprié pour des objets tels que les icônes, les images de pointeurs de souris, ou des données pixel chargées à partir d'une source externe.

Les styles

La plupart des commandes de dessins ont un paramètre de "style" associé, qui est une liste d'association plannifiant les propriétés de style comme la couleur de remplissage ou l'épaisseur des lignes pour des valeurs fournies par l'illustration. Plus tard, nous espérons intégrer complétement la mise à disposition des styles avec un moteur de style CSs (que nous espérons aussi utiliser pour choisir les variantes des éléments graphiques) dans le but de faciliter la personnalisation.

Les kits de dessin

Le dessin dans berlin, comme décrit ci-dessus, est négocier par une interface unique, de haut niveau appelé DrawingKit. Différentes implémentations du DrawingKit enveloppe différentes bibliothèques de dessins inférieures, remplissant les différences entre l'interface de haut niveau qu'il exporte et les primitives bas niveau supportées par la bibliothèque de dessin.

Les tableaux (drawables)

Chaque instance d'un DrawingKit. possède un Drawable associé, qui est un objet représentant le "support" sur lequel le kit de dessin opérera. Cela peut être un CRT, une feuille de papier, un LCD, ou un périphérique imaginaire que le DrawingKit peut simuler. En ce moment, tous les Drawable existant, fournissent les informations de dpi au DrawingKit et gère la pile de coupure ; plus tard, cela pourra être étendue pour fournir plus d'informations pour le DrawingKit.

Résolution de couleur

Les modèles d'approximation de couleur

Résolution particulière

Approximation spatiale & ébauche