Documente Academic
Documente Profesional
Documente Cultură
Curs – 7
CLASA GRAPHICS
Un applet foloseste metoda drawString() pentru a desena text . Fontul si culoarea textului au fost deja
alese anterior desenarii textului .
Textul nu este singurul lucru pe care il putem desena in fereastra appletului ; tot aici putem insera linii ,
cercuri , ovaluri , dreptunghiuri si alte forme geometrice .
Majoritatea operatiilor de desenare sunt metode definite in clasa Graphics . Intr-un applet nu este
nevoie sa cream un obiect Graphics pentru a putea desena ceva - unul dintre argumentele metodei
paint() este un obiect Graphics - acesta reprezinta fereastra appletului iar metodele sale sunt folosite
pentru a desena in applet .
Clasa Graphics este parte a pachetului java.awt , deci toate appleturile care deseneaza ceva trebuie sa
foloseasca instructiunea import pentru a putea folosi aceasta clasa .
In exemplul urmator avem un applet care foloseste drawString() pentru a afisa un text :
import java.awt.Graphics;
public class Harta extends java.applet.Applet {
public void paint(Graphics ecran) {
ecran.drawString("Harta",185,75);
}
}
Pentru a insera acest applet trebuie sa cream un fisier HTML ca cel de mai jos :
<body bgcolor=c4c4c4>
<div align=center>
<applet code="Harta.class" height=350 width=350>
</applet>
</div>
</body>
Toate comenzile de baza de desenare sunt metode ale clasei Graphics , apelate din cadrul metodei
paint() . Acesta este locul ideal unde se pot desfasura toate operatiile de desenare deoarece metoda este
apelata automat oricand este nevoie de reimprospatarea ferestrei appletului . Daca fereastra altui
program se suprapune peste applet si acesta trebuie redesenat , introducerea tuturor operatiilor de
desenare in metoda paint() asigura ca nici o parte a ferestrei nu va fi eventual stricata .
DESENAREA SI UMPLEREA
Pentru majoritatea formelor pe care putem sa le desenam intr-un applet exista doua tipuri de metode :
de desenare - care deseneaza conturul formei , si de umplere - care umplu forma cu culoarea curenta .
In fiecare tip de metoda , conturul obiectului este desenat si el cu culoarea curenta .
LINIILE
Metoda drawLine() este folosita pentru a desena o linie intre doua puncte . Metoda primeste patru
argumente : coordonatele x , y ale punctului de inceput si coordonatele x , y ale punctului final :
drawLine (x1 , y1 , x2 , y2 );
1
ecran.drawLine(185,80,222,80);
DREPTUNGHIURI
Clasa Graphics contine metode pentru doua tipuri de dreptunghiuri : normale si cu colturile rotunjite .
Ambele tipuri de dreptunghiuri pot fi desenate sub forma de contur sau umplute cu culoarea curenta .
Pentru a desena un dreptunghi normal se foloseste metoda drawRect() pentru contururi si fillRect()
pentru forma umplute .
Ambele metode preiau patru argumente :
- coordonatele x si y ale coltului din stanga-sus al dreptunghiului
- latimea dreptunghiului
- inaltimea dreptunghiului
ecran.drawRect(2,2,345,345);
Aceasta instructiune adauga un contur dreptunghiular aproape de marginile ferestrei appletului . Daca
am fi folosit metoda fillRect() toata zona appletului ar fi fost acoperita de un dreptunghi plin de culoare
, fapt ce ar fi dus la acoperirea textului .
ecran.drawRoundRect(182,61,43,24,10,8);
Rezultatul acestei instructiuni este desenarea unui dreptunghi rotunjit cu o latime de 43 de pixeli si o
inaltime de 24 de pixeli . Zona dreptunghiulara pentru fiecare colt rotunjit este de 10 pixeli latime si 8
inaltime .
POLIGOANE
- ca o pereche de tablouri cu intregi , dintre care unul pastreaza valorile coordonatei x si celalalt
pastreaza toate valorile coordonatei y
- ca un obiect Polygon creat folosind un tablou cu valori intregi ale coordonatei x si un tablou
cu valori intregi ale coordonatei y
A doua metoda este mai flexibila deoarece permite adaugarea individuala a punctelor unui poligon
inainte de desenarea sa .
In afara de coordonatele x si y trebuie sa specificam si numarul de puncte al poligonului . Nu se pot
specifica mai multe coordonate x , y decat numarul de puncte si nici invers . In oricare din aceste cazuri
compilatorul va semnala eroare .
pentru a crea un obiect Poligon primul pas este crearea unui poligon gol , printr-o instructiune new :
Putem crea un poligon si pornind de la un set de puncte , folosind tablouri cu valori intregi . Aceasta
necesita un apel catre constructorul Polygon(int[],int[],int[]) , unde se specifica tabloul cu valori pentru
coordonata x , tabloul cu valori pentru coordonata y si numarul de puncte ( colturi ) :
2
int x[]={10,20,30,40,50};
int y[]={15,25,35,45,55};
int puncte=x.length;
Polygon polig=new Polygon(x,y,puncte);
Dupa crearea obiectului Polygon se pot adauga puncte folosind metoda addPoint() . Aceasta preia ca
argumente coordonatele x si y si adauga punctul in poligon :
polig.assPoint(60,65);
Atunci cand obiectul poligon are toate punctele el poate fi desenat folosind una dintre metodele
drawPoliyon() sau fillPolygon() . Aceste metode au drept unic argument obiectul Polygon :
ecran.drawPoligon(polig);
Daca folosim metoda drawPolyg() putem inchide poligonul stabilind ultimele coordonate x , y identice
cu primele . Altfel poligonul va ramane deschis .
Metoda fillPolygon() inchide automat forma poligonala fara a mai fi nevoie de specificarea coordonatei
finale identice cu cea initiala .
Incepand cu versiunea 1.1 a Java metoda drawPolygon() inchide si ea automat poligonul , daca dorim
un poligon deschis folosim o alta instructiune : drawPolyline() - cu aceeasi functionare ca
drawPolygon() din Java anterior versiunii 1.1 .
int x[]={10,234,253,261,344,295,259,205,211,195,191,120,94,81,12,10};
int y[]={12,15,25,71,209,278,310,274,188,171,174,118,56,68,49,37,12};
int pct=x.length;
Polygon polig=new Polygon(x,y,pct);
ecran.drawPolygon(polig);
Clasa Plygon face parte din pachetul java.awt , deci acesta trebuie importat prin adaugarea instructiunii
urmatoare la inceputul appletului :
import java.awt.Polygon;
OVALE
Deoarece ovalele nu au colturi asa ca respectivele coordonate x si y pe care le primesc aceste metode se
refera de fapt la punctul din stanga-sus al zonei in care va fi desenat ovalul , aflandu-se de fapt la
stanga si mai sus decat forma geometrica propriu-zisa .
ecran.fillOval(235,140,15,15);
ecran.fillOval(225,130,15,15);
ecran.fillOval(245,130,15,15);
Acestea sunt metode de umplere iar rezultatul lor vor fi trei cercuri colorate in culoarea curenta .
ARCE DE CERC
3
Desenarea arcelor de cerc este o operatie ceva mai complexa ; un arc este parte a unui oval , fiind
implementat de fapt ca parte a unui oval partial desenat .
Arcele sunt folosite cu ajutorul metodelor drawArc() si fillArc() , care preiau sase argumente :
- coordonatele x si y ale ovalului din care face parte arcul
- latime si inaltime acestui oval
- unghiul de unde incepe trasarea arcului
- numarul de grade al arcului
Primele patru argumente sunt identice cu cele din cazul ovalelor si au acelasi rol ca si in acel caz .
Unghiul de inceput al arcului ia valori intre 0 si 359 de grade si creste in sens trigonometric ( invers
acelor de ceas ) . Pe un cerc de forma unui ceas putem vedea 0 grade in dreptul orei 3 , 90 de grade la
ora 12 , 180 de grade la ora 9 si 270 de grade la ora 6 .
numarul de grade pe care se intinde arcul ia valori de la 0 la 359 tot in sens contrar acelor de ceas sau
de la 0 la -359 in sensul acelor de ceas .
Arcele umplute sunt desenate ca si cand ar fi felii dar , in loc sa se uneasca direct cele doua puncte
terminale acestea sunt unite prin intermediul centrului formei eliptice ( ovalului ) .
ecran.drawArc(20,25,315,150,5,-190);
- ovalul fiecarui arc are o latime si o inaltime egale cu 10 pixeli , deci ovalul devine de fapt cerc
- fiecare arc va incepe la 0 grade si va merge 180 de grade in sensul acelor de ceas desenand un
semicerc
for(int ax=50;ax<150;ax+=10)
for (int ay=120;ay<320;ay+=10)
ecran.drawArc(ax,ay,10,10,0,-180);
COPIEREA SI STERGEREA
Clasa Graphics contine si cateva functii de gen cut&paste , aplicabile ferestrei appletului :
- metoda copyArea() - care copiaza o regiune dreptunghiulara a ferestrei intr-o alta regiune a
ferestrei
- metoda clearRect() - care decupeaza o regiune dreptunghiulara din fereastra appletului
Urmatoarea instructiune copiaza o regiune de 100 pe 100 de pixeli intr-o zona aflata cu 50 de pixeli
mai la dreapta si cu 25 de pixeli mai jos :
ecran.copyArea(0,0,100,100,50,25);
Metoda clearRect() preia aceleasi patru argumente ca si metoda drawRect() sau fillRect() , umpland
regiunea dreptunghiulara astfel creata cu culoarea curenta de fundal a appletului .
4
Daca dorim sa stergem intreaga fereastra applet putem determina mai intai dimensiunea ferestrei
folosind metoda size() . Aceasta returneaza un obiect Dimension , care poseda variabilele width si
height ; acestea reprezinta dimensiunile appletului .
ecran.clearRect(0,0,size().width,size().height);
In versiunile mai noi de Java compilatorul ne va anunta ca functia size() este depreciata , ea putand fi
inlocuita cu getSize() , care functioneaza identic .
TEXT SI FONTURI
Obiectele clasei java.awt.Font sunt folosite pentru a putea utiliza metoda drawString() cu diferite tipuri
de caractere . Obiectele Font contin numele , stilul si dimensiunea in puncte a unui font . O alta clasa ,
FontMetrics , ofera metode pentru determinarea dimensiunilor si a caracterelor afisabile cu un anumit
font , care pot fi folosite pentru formatarea sau centrarea textului .
- numele fontului
- stilul fontului
- dimensiunea in puncte a fontului
Numele poate fi denumirea unui font specifc - de exemplu Arial sau Garamond - care va poutea fi
folosit daca este disponibil pe sistemul unde ruleaza programul . Exista si alte nume care pot fi folosite
pentru selectarea fonturilor interne ale Java : TimesRoman , Helvetica , Courier , Dialog si DialogInput
.
In versiunile mai noi de Java numele fonturilor TimesRoman , Helvetica si Courier trebuie inlocuite cu
serif,sanserif si monospaced .
Stilul de font poate avea trei valori , apelate folosind constantele Font.PLAIN , Font.BOLD si
Font.ITALIC . Aceste constante sunt intregi si pot fi insumate pentru a obtine o combinatie de efecte .
Dimensiunea fontului este data in puncte , ca in exemplul de mai jos care implementeaza un font
Dialog de 24 de puncte , cu caractere bold si italice :
ecran.setFont(f);
Textul poate fi afisat intr-o fereastra applet cu ajutorul lui drawString() . Aceasta functie foloseste
fontul curent selectat - sau cel implicit .
Urmatoarea metoda paint() creaza un nou obiect Font , stabileste fontul curent la acest obiect si
afiseaza un text la coordonatele 10 , 100 :
Valoarea x reprezinta locul de inceput al marginii din stanga a textului iar y este valoarea la care se
afiseaza linia de baza a sirului de text .
5
AFLAREA DE INFORMATII DESPRE FONT
Clasa FontMetrics poate fi folosita pentru a afla informatii detaliate despre fontul curent , cum ar fi
latimea sau inaltimea caracterelor pe care le paote afisa .
Pentru a folosi metodele acestei clase , trebuie mai intai creat un obiect FontMetrics prin metoda
getFontMetrics() . Aceasta metoda primeste un singur argument : un obiect Font .
Un obiect FontMetrics poate apela mai multe metode :
- stringWidth(String) - intoarce latimea totala a sirului , in pixeli
- charWidth(char) - intoarce latimea unui caracter dat
- getHeight() - intoarce inaltimea totala a fontului
import java.awt.Font;
import java.awt.Graphics;
import java.awt.FontMetrics;
Determinarea dimensiunii ferestrei appletului in cadrul sau este preferabila metodei de definire a unei
dimensiuni statice in applet , deoarece este mai flexibila . Putem modifica codul sursa HTML al
appletului in pagina web fara a modifica si programul nostru , acesta functionand in continuare corect .
CULORI
Clasele Color si ColorSpace din pachetul java.awt pot fi folosite pentru a aduce culoare in appleturi si
aplicatii . Cu ajutorul acestor clase putem stabili culorile curente folosite in operatiile de desenare , ca
si culoarea de fundal pentru un applet sau alte ferestre . De asemenea putem translata o culoare dintr-un
sistem de descriere in altul .
In mod prestabilit Java foloseste culorile conform sistemului RGB . In acest sistem o culoare este
descrisa prin cantitatea de rosu , verde si albastru pe care o contine ( red - green - blue ) . Fiecare dintre
cele trei componente poate fi reprezentata cu un intreg din gama 0 - 255 . Combinatia 0,0,0 reprezinta
negru . Putem specifica o combinatie RGB si prin trei valori in virgula mobila , in gama 0 - 1 .
Un alt sistem de culori - sau spatiu de culori - este CYMK , care specifica o culoare prin cantitatea de
azuriu ( cyan ) , mov ( magenta ) , galbe ( yellow ) si negru ( black ) .
Java2 suporta folosirea oricarui tip de spatiu de culori atata timp cat folosim un obiect ColorSystem
care defineste sistemul respectiv de descriere a culorilor .
Reprezentarea interna a culorilor in Java folosind RGB este spatiul de culoare utilizat in program ;
dispozitivele de iesire pot avea si ele propriile spatii de culoare .
In practica o culoare definita RGB poate sa apara usor diferit pe un alt dispozitiv de iesire decat
monitorul . Pentru un control mai bun asupra culorii putem folosi ColorSpace sau alte clase din
pachetul java.awt.color .
6
Pentru a crea o culoare avem doua metode de apelare a metodei constructor Color :
Urmatoarea instructiune stabileste culoarea curenta pentru obiectul ecran folosind una dintre variabilele
standard de clasa :
ecran.setColor(Color.pink);
Din acest moment toate operatiile de desenare vor folosi aceasta culoare .
Putem stabili culoarea de fundal intr-o fereastra applet folosind metodele setBackground() si
setForeground() . Acestea sunt mostenite de clasa Applet de launa dintre superclasele sale asa incat
toate appleturile create vor mosteni si ele aceste metode .
Urmatoarea instructiune stabileste culoarea curenta pentru ecran - un obiect Graphics - ca fiind aceeasi
cu fundalul appletului :
ecran.setColor(getBackground());
7
- metode speciale de umplere cu degradeuri si texturi
- tuse care definesc grosime si stilul desenului
- posibilitati de netezire a marginilor obiectelor desenate ( anti-aliasing )
Pentru toate operatiile de desenare de pana acum singurul spatiu de coordonate folosit era cel al
dispozitivului . Se specificau coordonatele x si y ale unei suprafete de iesire - ca fereastra Applet - si
aceste coordonate erau folosite pentru a desena linii , text si altele .
Java2D are nevoie de un al doilea spatiu de coordonate , la care facem referire atunci cand cream si
desenam un obiect . Acesta este numit spatiu de coordoante al utilizatorului .
Inainte de a folosi operatii de desenare Java2D in program , spatiul dispozitivului si cel al utilizatorului
au puctul de coordonate 0 , 0 in acelasi lod , coltul din stanga-sus al zonei de desenare .
Coordonata 0,0 a spatiului utilizator se poate depalsa ca urmare a unei operatii de desenare 2D . Chiar
si axele x , y se pot modifica drept urmare a unei rotiri 2D .
Obiectul ecran2D din exemplul nostru a fost produs printr-o conversie cast . El este obiectul ecran ,
convertit dintr-o clasa in alta .
Toate operatiile grafice Java2D trebuie apelate pentruun obiect Graphics2D ; aceasta clasa ,
Graphics2D , face si ea parte din java.awt .
CULORI 2D
Culorile sunt specificate folosind metoda setColor() , care funtioneaza la fel cu metoda Graphics cu
acelasi nume - diferenta constand in obiectul argument care acum este de tip Graphics2D .
MODELE DE UMPLERE
Texturile sau modelele de umplere , definesc modul cum este umplut un obiect . In Java2D putem
folosi o culoare solida , un degrade , o textura sau un model oarecare .
Un model de umplere este definit prin folosirea metodei setPaint() a clasei Graphics2D , avand ca
argument un obiect Paint . Interfata Paint este implementata de fiecare clasa care poate juca rolul unui
model de umplere - ca de exemplu GradientPaint , TexturePaint sau Color .
O umplere in degrade inseamna o trecere gradata de la o culoare la alta intre doua coordonate . Aceasta
deplasare a culorii poate aparea o singura data intre cele doua coordonate , caz in care se numeste
aciclica sau poate apare in mod repetat , caz in care se numeste ciclica .
Punctele de coordonate dintr-un degrade nu se refera direct la punctele obiectului Graphics2D pe care
desenam . De fapt ele se refera la spatiul utilizator si se pot afla chiar in afara obiectului ce urmeaza a fi
umplut cu respectivul degrade .
GradientPaint(x1,y1,culoare1,x2,y2,culoare2);
8
Punctul x1,y1 este punctul de unde incepe culoare culoare1 iar x2,y2 este punctul unde se termina
trecerea la culoare2 .
GradientPaint(x1,y1,culoare1,x2,y2,culoare2,true);
Ultimul argument este o valoare booleana care are valoarea true pentru degrdeul ciclic ; argumentul
false poate fi folosit pentru varianta aciclica sau poate fi omis .
Dupa ce am definit un obiect GradientPaint il vom declara atribut curent de desenare cu setPaint() :
Toate operatiile de desenare care vor urma pentru obiectul ecran2D vor folosi acest model de umplere .
Stilurile de terminatie ( endcap ) sunt aplicate liniilor care nu se conecteaza la alte linii . Stilurile de
imbinare ( juncture ) sunt aplicate capetelor de linie care se conecteaza la alte linii .
Stilurile posibile pentru terminatii sunt CAP_BUTT ( fara terminatie ) , CAP_ROUND ( pentru
terminatii circulare ) si CAP_SQUARE ( pentru terminatii rectangulare )
Diferenta intre primul si ultimel stil este foarte mica , o linie cu CAP_SQUARE fiind mai lunga ,
datorita terminatiei de forma patrata .
Stilurile de imbinare sunt JOIN_MITER ( pentru imbinarea prin prelungirea muchiilor exterioare ) ,
JOIN_ROUND ( pentru imbinarea rotunjita ) si JOIN_BEVEL ( pentru o imbinare tesita ) .
Exemplul de mai jos creaza un obiect BasicStroke si il stabilesc drept stil de tusa curent :
BasicStroke creion=BasicStroke(2.0f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND);
ecran2D.setStroke(creion);
Efectul liniilor de mai sus este o tusa de 2 pixeli , terminatii netede ale segmentelor si colturi de
imbinare rotunjite .
Clasa Graphics2D nu poseda metode diferite pentru desenarea fiecareia dintre forme . In schimb se
defineste mai intai forma dorita si apoi se foloseste ca argument pentru una dintre metodele fill() sau
draw() .
LINII
Se creaza folosind clasa Line2d.Float . Aceasta clasa preia patru argumente : coordonetele x , y ale unui
capat de segment si coordonatele x , y ale celuilalt capat :
9
Aceasta instructiune creeaza o linie intre punctele 60,5 si 13,28 . Mentionam utilizarea literei f pentru
specificarea tipului float pentru argumente .
DREPTUNGHIURI
Acestea sunt create folosind clasele Rectangle2D.Float sau Racrtangle2D.Double . Diferenta intre cele
doua este tipul argumentelor .
ELIPSE
Obiectele ovale sunt numite in Java2D elipse si pot fi create cu clasa Ellipse2D.Float . Este nevoie de
patru argumente : coordonatele x , y , latimea si inaltimea .
Instructiunea de mai jos creaza o elipsa la coordonata 113,25 cu o latime de 22 pixeli si o inaltime de
40 pixeli :
ARCE
Acestea sunt create prin clasa Arc2D.Float . Sunt create asemanator cu versiunea lor non-2D dar cu o
diferenta : putem stabili modul de inchidere .
Arc2D.Float primeste sapte argumente . Primele patru se refera la elipsa din care face parte arcul :
coordonatele x , y , latimea si inaltimea . Ultimele trei se refera la unghiul de unde incepe desenarea ,
numarul de grade pe care se intinde si un intreg care stabileste modul de inchidere .
Exista o deosebire fata de arcele non-2D : numarul de grade pe care se intinde arcul 2D este specificat
ca avand sensul pozitiv in sensul acelor de ceas .
Ultimul argument foloseste una dintre variabilele de clasa : Arc2D.OPE ( pentru arc dechis ) ,
Arc2D.CHORD ( pentru un arc ale carui capete sunt unite printr-o linie dreapta ) si Arc2D.PIE ( pentru
un arc cu capetele unite prin intermediul centrului elipsei . Mai trebuie mentionat ca stilul de inchidere
Arc2D.OPEN nu se aplica arcelor umplute ; un astfel de arc umplut va fi autonat inchis cu stilul
Arc2D.CHORD .
Instructiunile de mai jos creaza un arc dintr-o elipsa cu coordonatele 27,22, 42 de pixeli latime si 30
inaltime . Arcul incepe la 33 de grade , se intinde pe 90 de grade in sensul acelor de ceas si va fi inchis
prin intermediul centrului elipsei :
POLIGOANE
Acestea sunt create in Java2D prin deplasarile dintr-un punct al poligonului in altul . Un poligon poate
fi format din linii drepte , curbe patratice sau curbe Bezier .
Deplasarile necesare pentru crearea poligonului sunt definite in obiectul GeneralPath , care apartine
pachetului java.awt.geom .
Metoda moveTo() a clasei GeneralPath este folosita pentru a crea primul punct al poligonului .
Urmatoarea instructiune poate fi folosita pentru a incepe poligonul de la coordonatele 5,0 :
polig.moveTo(5f,5f);
10
Dupa crearea primului punct , metoda lineTo() se foloseste pentru crearea unei linii care incepe din
punctul curent si se termina intr-un nou punct . Metoda primeste doua argumente : coordonatele x si y
ale noului punct .
Urmatoarele instructiuni creaza trei linii pentru obiectul polig :
polig.lineTo(205f,0f);
polig.lineTo(205f,90f);
polig.lineTo(5f,90f);
Metodele lineTo() si moveTo() primesc ca argumente ale coordonatelor valori float() . Daca vrem sa
inchidem un poligon se poate folosi metoda closePath() fara nici un argument :
polig.closePath();
Aceasta metoda inchide un poligon prin conectarea punctului curent cu punctul specificat in cel mai
recent apel de metoda moveTo() . Putem inchide poligonul si fara aceasta metoda , prin folosirea
metodei LineTo() care conecteaza punctul curent cu punctulinitial al poligonului .
O data creata forma poligonala ea poate fi reprezentata ( desenata ) ca orice alt obiect , cu metodele
fill() sau draw() .
DESENAREA OBIECTELOR
Toate obiectele pe care le vom desena in continuare folosesc metode ale clasei Graphics2D : draw() si
fill() . Aceste metode primesc ca unic argument obiectul ce trebuie desenat .
Sirurile sunt desenate in Java2D tot cu drawString() . Aceasta preia trei argumente : obiectul String si
coordonatele x si y - cu mentiunea ca aceste coordonate sunt de tip float , ca la toate coordonatele din
Java2D .
import java.awt.*;
import java.awt.geom.*;
11
f1.lineTo(195F,174F);
f1.lineTo(191F,118F);
f1.lineTo(120F,56F);
f1.lineTo(94F,68F);
f1.lineTo(81F,49F);
f1.lineTo(12F,37F);
f1.closePath();
ecran2D.fill(f1);
//Desenare elipse
ecran2D.setColor(Color.black);
BasicStroke creion2=new BasicStroke();
ecran2D.setStroke(creion2);
Ellipse2D.Float e1=new Ellipse2D.Float(235,140,15,15);
Ellipse2D.Float e2=new Ellipse2D.Float(225,130,15,15);
Ellipse2D.Float e3=new Ellipse2D.Float(245,130,15,15);
ecran2D.fill(e1);
ecran2D.fill(e2);
ecran2D.fill(e3);
}
}
12