>El &chalk; és infinitament extensible amb endollables. Les eines, els filtres, grans troços de la interfície d'usuari i fins i tot espais de color són endollables. De fet, el &chalk; reconeix aquestes sis tipus d'endollables: </para>
>El &chalk; mateix està composat per tres biblioteques en capes i un directori amb algunes classes comunes de suport: chalkcolor, chalkimage i chalkui. Dins del &chalk;, els objectes es poden identificar per un <classname
>Unes paraules sobre compatibilitat: el &chalk; està encara en desenvolupament. Des del &chalk; 1.5 a l'1.6 no s'esperen massa canvis a l'API, però potser n'hi ha alguna. Des del &chalk; 1.6 al 2.0, hi haurà el canvi de les &Qt;3 a les &Qt;4, del &kde;3 al &kde;4, del <command
>: s'esperen molts canvis. Si desenvolupeu un endollable per al &chalk; i escolliu fer-ho en la versió del repositori subversion del &chalk;, hi ha grans possibilitats que us ajudem a portar-lo. Aquests canvis també portaran que parts d'aquest document esdevinguin obsoletes. Comproveu sempre l'última documentació de l'API o els fitxers de capçalera instal·lats al vostre sistema. </para>
>La biblioteca libchalkimage carrega els endollables de filtre i paintop i és el responsable de treballar amb dades d'imatge: canviant píxels, composant i pintang. Els pinzells, les paletes, els gradients i els patrons també els carrega la libchalkimage. El nostre objectiu definit és fer la libchalkimage independent del &koffice;, però actualment compartim el gradient carregant codi amb el &koffice;. </para
>No és fàcil de moment afegir nous tipus de recursos com els pinzells, les paletes, els gradients o patrons al &chalk;. (Afegir nous pinzells, paletes, gradients i patrons és fàcil, és clar.) El &chalk; segueix les línies mestres del projecte Create (<ulink url="http://create.freedesktop.org/"
>) per a això. Afegir suport per al format de pinzell del Photoshop's necessita haquejar la libchalkimage; afegir més fitxers de dades de pinzell del Gimp, no. </para
>Les operacions de dibuix o paintops són el conjunt d'operacions als què tenen accès les eines de dibuix com el de mà alçada o el cercle. Són exemples de paintops el lapis, l'aerosol o l'esborrador. Els paintops ha d'extendre la classe base <classname
>KisPaintop</classname
>. Exemples de nous paintops poden ser un pinzell pastel, un pinzell de pintura a l'oli o un pinzell programable complex.</para
>La biblioteca libchalkui carrega les eines i els endollables visualització. Aquesta biblioteca és part del &koffice;, però també conté un número d'estris útils per a aplicacions gràfiques. Potser haurem de dividir aquesta biblioteca en chalkpart i chalkui a la versió 2.0. De moment, als escriptors d'scripts no se'ls dóna accés a aquesta biblioteca i els escriptors d'endollables només poden usar aquesta biblioteca quan escriuen eines o endollables de visualització. La <classname
> carrega els següents tipus d'endollables: </para>
<itemizedlist>
<listitem
><para
>Les eines es deriven de <classname
>KisTool</classname
> o una de les classes bàsiques d'eines especialitzades com a <classname
>KisToolPaint</classname
>, <classname
>KisToolNonPaint</classname
> o <classname
>KisToolFreehand</classname
>. Una nova eina pot ser una eina de selecció d'objecte de primer pla. Les eines de dibuix (i això inclou eines que dibuixen a la selecció) pot usar qualsevol paintop per a determinar la manera en què es canvien els píxels.</para
></listitem>
<listitem
><para
>Els endollables de visualització són KParts ordinàries que usen <command
> per a insinuar-se a la interfície d'usuari del &chalk;. Les opcions de menú, els diàlegs, les barres d'eines — i qualsevol mena d'extensió d'interfície d'usuari pot ser un endollable de visualització. De fet, una important funcionalitat com el suport d'script del &chalk; està escrita com a un endollable de visualització.</para
>. Els filtres llegeixen i escriuen dades d'imatge en qualsevol de la miríada de formats d'imatges existents. Un exemple del nou filtre d'importació/exportació del &chalk; pot ser un filtre PDF. Els filtres els carregen les biblioteques del &koffice;. </para>
>Els endollables s'escriuen en C++ i poden usar tots els API de desenvolupador del &kde;, les &Qt; i el &chalk;. Només els endollables de visualització han d'usar l'API del &koffice;. No patiu: l'API del &chalk; és prou clara i prou extensament documentada (per a programari lliure) i escriure el vostre primer filtre és fàcil de debò. </para
>Si no voleu usar el C++, podeu escriure scripts en Python o Ruby; són coses diferents, però, i no podeu actualment escriure eines, espais de color, paintops o filtres d'importació/exportació com a scripts. </para
>Els endollables del &chalk; usen parts del mecanisme del &kde;'s per a carregar, de manera que la documentació de les parts, a <ulink url="http://developer.kde.org"
>La vostra distribució ha de tenir els fitxers de capçalera relevants instal·lats amb el &chalk; mateix, o potser ha separat els fitxers de capçalera a un paquet &koffice; dev o &chalk; dev. Podeu trobar la documentació de l'API per a l'API pública del &chalk; a <ulink url="http://koffice.org/developer/apidocs/chalk/html/"
>. La manera més fàcil de començar és donar un cop d'ull al projecte chalk-plugins des del repositori de Subversion del &koffice; i usar-lo com a base per al vostre propi projecte. Volem preparar un paquet d'endollables bàsic del &chalk; per al KDevelop, però no hem tingut temps encara per a fer-ho. </para>
> Aquest és el makefile per a un endollable de filtre. Reemplaceu <replaceable
>LIBRARYNAME</replaceable
> pel nom de la vostra feina, i ja estareu. </para
><para
>Si el vostre endollable és de visualització, haureu d'instal·lar també un fitxer <literal role="extension"
>.rc</literal
> amb entrades per a barres de menú i barres d'eines. De la mateixa manera, us caldrà instal·lar cursors i icones. Això es fa mitjançant els encanteris del <filename
>Els filtres d'importació i exportació de fitxer usen el marx de filtres genèric del &koffice; i cal que en parlem per separat. </para>
</sect4>
<sect4 id="d-p-c-a-boilerplate">
<title
>Boilerplate</title>
<para
>També us caldrà una mica de codi de boilerplate cridat per la part del marc del &kde; per a provocar l'endollable —, un fitxer de capçalera i un fitxer d'implementació. </para
KisToolRegistry * r = dynamic_cast<KisToolRegistry*>( parent );
r -> add(new KisToolStarFactory());
}
}
ToolStar::~ToolStar()
{
}
#include "tool_star.moc"
</programlisting>
</para>
</sect4>
<sect4 id="d-p-c-a-registries">
<title
>Registres</title>
<para
>Les eines les carrega l'eina de registre i els registres mateixos amb l'eina de registre. Els endollables com les eines, els filtres i els paintops es carreguen només un cop: els endollables de visualització es carreguen per a cada visualització que es crea. Noteu que registrem factories, parlant genèricament. Per exemple, amb les eines, es crea una nova instància de cada eina per a cada punter (ratolí, estil, esborrador) per a pocs. I es crea un nou paintop cada cop que una eina rep un esdeveniment del ratolí. </para>
<para
>Els filtres criden el registre de filtres: <programlisting
(void) new KAction(i18n("&Shear Image..."), 0, 0, this, SLOT(slotShearImage()), actionCollection(), "shearimage");
(void) new KAction(i18n("&Shear Layer..."), 0, 0, this, SLOT(slotShearLayer()), actionCollection(), "shearlayer");
m_view = (KisView*) parent;
}
</programlisting>
</para
><para
>Recordeu que això vol dir que es crearà un endollable de visualització per a cada vista que crei l'usuari; dividir una vista vol dir carregar de nou tots els endollables. </para>
>. Els endollables del &chalk; 1.6 seran probablement binàriament incompatibles amb els de l'1.5 i necessitaran la versió número 3. Els endollables del &chalk; 2.0 plugins necessitaran la versió número 3. Sí, això no és completament lògic. </para>
>Implementar un espai de color és prou fàcil. El principi general és que els espais de color treballen en un rang simple de bytes. La interpretació d'aquests bytes depén de l'espai de color. Per exemple, un píxel en 16-bit GrayA està composat de quatre bytes: dos per al valor de gris i dos per al valor alfa. Sou lliures d'usar una estructura per a treballar amb format de memòria d'un píxel a la vostra implementació d'espai de color, però aquesta representació no s'exporta. L'única manera en què la resta del &chalk; pot saber quins canals i tipus de canals composen el vostre espai de color és mitjançant la classe <classname
>Aquesta classe defineix els canals que fan un píxel en un espai de color particular. Un canal té les següents característiques importants: </para>
<itemizedlist>
<listitem
><para
>un nom per a mostrar-lo a la interfície d'usuari</para
></listitem>
<listitem
><para
>una posició: el byte on comencen els bytes que representen aquest canal al píxel.</para
></listitem>
<listitem
><para
>un tipus: color, alfa, substància o substrat. El color ñes un color pla, alfa és la transparència, substància és una representació de la quantitat de pigment o coses com aquestes, substracte és la representació del llenç. (Noteu que això es pot rearranjar en un moment.)</para
></listitem>
<listitem
><para
>un valor de tipus: byte, short, integer, float o un altre.</para
></listitem>
<listitem
><para
>mida: el múmero de bytes que agafa aquest canal</para
></listitem>
<listitem
><para
>color: una representació <classname
>QColor</classname
> d'aquest canal per a la visualització de la interfície de l'usuari, per exemple en histogrames.</para
></listitem>
<listitem
><para
>una abreviació per a usar-la a la IGU quan no hi ha molt d'espai</para
>Un endollable d'espai de color pot suportar qualsevol subconjunt d'aquestes possibles operacions de composició, però el conjunt sempre ha d'incloure "OVER" (el mateix que "NORMAL") i "COPY". La resta són més o menys opcionals, malgrat que com més és millor, és clar. </para>
> es pot dividir en uns quants grups: conversió, identificació i manipulació. </para
><para
>Totes les classes han de ser capaces de convertir un píxel a 8 bit RGB (és a dir, un <classname
>QColor</classname
>), i preferiblement també a 16 bit L*a*b. Addicionalment, hi ha un mètode per a convertir a qualsevol espai de color des de l'actual espai de color. </para
><para
>Els espais de color es descriuen amb el vector <classname
>KisChannelInfo</classname
>, el número de canals, el número de bytes en un píxel, si dóna suport a imatges d'alt rang dinàmic i més. </para
><para
>La manipulació és per exemple la combinació de dos píxels en un nou píxel: bitBlt, obscuriment o convulció de píxels. </para
><para
>Si us plau, consulteu la documentació de l'API per a una descripció completa de tots els mètodes que necessiteu per a implementar-los en un espai de color. </para
><para
><classname
>KisAbstractColorSpace</classname
> implementa molts dels mètodes virtuals de <classname
>KisColorSpace</classname
> usant funcions des de la biblioteca <command
>lcms</command
>. A sobre de <classname
>KisAbstractColorSpace</classname
> hi ha classes base d'espais de color per a espais de color de 8 i 16 bit enters i 16 i 32 bit float que defineixen les operacions comunes per a moure entre profunditats de bit. </para>
>Els filtres són endollables que examinen els píxels d'una capa i en fa canvis. Malgrat que el &chalk; usa un rerefons de memòria en mosaic per a emmagatzemar píxels, els escriptors de píxels no s'han de preocupar per això. Quan escriviu un endollable de filtre per a l'API imaging de &Java;, el Photoshop o el Gimp, heu d'anar amb compte amb les vores del mosaic i <quote
>Noteu que és fàcil, teòricament, reemplaçar el rerefons d'emmagatzement de dades d'imatge en mosaic actual amb un altre, però els rerefons no són endollables reals de moment, per raons de representació.</para
>El &chalk; usa iteratrs per a llegir i escriure valors de píxel. Alternativament, podeu llegir un bloc de píxels en una memòria intermèdia, jugar amb ell i després escriure-hi com a un bloc. Però això no és necessàriament més eficient, pot ser finsi tot més lent que usar els iterators; pot ser només més convenient. Mireu la documentació de l'API. </para
>Les imatges del &chalk; es componen de capes, de les quals hi ha actualment quatre tipus: capes de dibuix, capes de grup, capes d'ajustament (que contenen un filtre que s'aplica dinàmicament a les capes per sota del seu ajustament de capa) i capes de part. Els filtres sempre operen en capes de dibuix de la classe <classname
>. Un dispositiu de dibuix, al seu torn, dóna accès als píxels reals. </para
><para
>Els <classname
>PaintDevice</classname
>s passen generalment ajustats en punters compartits. Un punter compartit manté la traçabilitat dels llocs on s'usa el dispositiu de dibuix i esborra el dispositiu quan ja no s'usa enlloc. Reconeixereu la versió del punter compartit d'un dispositiu de dibuix pel seu sufix <literal
>SP</literal
>. Recordeu que mai heu d'esborrar explícitament un <classname
>KisPaintDeviceSP</classname
>. </para
><para
>Anem a examinar un filtre molt simple, un que inverteix cada píxel. El codi per a aquest filtre és al directori <filename class="directory"
> La funció passa dos dispositius de dibuix, un objecte de configuració (que no s'usa en aquest filtre simple) i un <varname
>rect</varname
>. El <varname
>rect</varname
> descriu l'àrea del dispositiu de dibuix on el filtre ha d'actuar. Aquesta àrea es descriu per números sencers, el que vol dir que no hi ha precisió sub-píxel. </para
><para
>El dispositiu de dibuix <varname
>src</varname
> és per a llegir-hi, el <varname
>dst</varname
> és per a escriure-hi. Aquests paràmetres poden apuntar al mateix dispositiu de dibuix, o ser dos diferents dispositius. (Nota: això pot canviar a un únic dispositiu de dibuix en el futur.) </para
><para
>Ara, anem a mirar el codi línia per línia: </para>
>Això crea un iterator per a llegir els píxels existents. El Chalk té tres tipus d'iterators: horitzontals, verticals i rectangulars. L'iterator rect agafa el camí més eficient per les dades de la imatge, però no garanteix res sobre la localització del següent píxel que retorna. Això vol dir que no podeu assegurar que el píxel que trobareu després sigui adjacent al píxel que teníeu. Els iterators de lína horitzontal i vertical sí que garanteixen la localització dels píxels que retornen. </para
>(2) Creem l'iterator de destí amb l'arranjament <literal
>write</literal
> en <literal
>true</literal
>. Això vol dir que si el dispositiu de dibuix de destí és més petit que el rect que escrivim, s'engrandirà automàticament per a encaixar cada píxel on hi iteratem. Noteu que aquí hi ha un bug potencial: si <varname
>dst</varname
> i <varname
>src</varname
> no són el mateix dispositiu, llavors és molt possible que els píxels que retornin els iterators no corresponguin. Per a cada posició a l'iterator, <varname
>src</varname
> pot ser, per exemple, a 165,200, ,mentre que <varname
>dst</varname
> pot ser a 20,8 — i per tant la còpia que presentem a sota pot estar distorsionant la imatge... </para
></callout>
<callout arearefs="invert3"
><para
>Voleu saber si un píxel està seleccionat? Això és fàcil usant el mètode <methodname
>isSelected</methodname
>. Però selectedness no és una propietat binària d'un píxel, un píxel pot estar mig seleccionat, poc seleccionat o quasi completament seleccionada. Aquest valor també el podeu obtenir des de l'iterator. Les seleccions són de fet un dispositiu de dibuix de màscara amb un rang d'entre 0 i 255, on 0 és completament deseleccionat i 255 completament seleccionat. L'iterator té dos mètodes: <methodname
>isSelected()</methodname
> i <methodname
>selectedNess()</methodname
>. Els primer retorna true si hi ha un píxel seleccionat en qualsevol extensió (és a dir, els valor de màscara és més gran que 1), l'altre returna el valor de màscara. </para
></callout>
<callout arearefs="invert4"
><para
>Com es fa notat amunt, aquest <literal
>memcpy</literal
> és un gran bug... <methodname
>rawData()</methodname
> retorna la matriu de bytes que és l'estat actual del píxel; <methodname
>oldRawData()</methodname
> retorna la matriu de bytes com era abans de crear l'iterator. En canvi, podem copiar aquí el píxel dolent. A la pràctica, això no passarà sovint, a no ser que el <varname
>dst</varname
> ja existeixi i no està aliniat amb el <varname
>src</varname
>. </para
></callout>
<callout arearefs="invert5"
><para
>Però això és correcte: per comptes d'esbrinar quin byte representa cada canal, usem una funció subministrada per tots els espais de color per a invertir el píxel actual. Els espais de color tenen un munt d'operacions de píxel que poseu usar. </para
></callout>
</calloutlist>
<para
>Això no és tot per a crear un filtre. Els filtres tenen dos altres components importants: un objecte de configuració i un estri de configuració. Els dos interactuen de costat. L'estri de configuració crea un objecte de configuració, però també s'omplirà des d'un objecte de configuració preexistent. Els objectes de configuració es poden representar com a XML i es poden crear des d'un XML. Això és el que fa possible l'ajustament de les capes. </para>
<sect3 id="developers-plugins-filters-iterators">
<title
>Iterators</title>
<para
>Hi ha tres tipus d'iterators: </para>
<itemizedlist>
<listitem
><para
>Línies horitzontals</para
></listitem>
<listitem
><para
>Línies verticals</para
></listitem>
<listitem
><para
>Iterors rectangulars</para
></listitem>
</itemizedlist>
<para
>Els iteratos de línia horitzontal i vertical tenen un mètode per a moure l'iterator a la següent fila o columna: <methodname
>nextRow()</methodname
> i <methodname
>nextCol()</methodname
>. Usar-la és molt més ràpid que crear un nou iterator per a cada línia o columna. </para
>Els iterators són segurs per als fils en el &chalk;, de manera que és possible dividir la feina en múltiples fils. En canvi, futures versions del &chalk; usarà el mètode <methodname
> per a determinar si el vostre filtre es pot aplicar els troços de la imatge (és a dir, tots els píxels modificats independentment, per comptes de canviats per algun valor determinat des d'un examen de tots els píxels de la imatge) i automàticament enfila l'execució del vostre filtre. </para>
> és una estructura que s'usa per a desar els arranjaments de filtres al disc, per exemple per a capes d'ajustament. L'endollable d'scripting usa el mapa de propietat que hi ha darrera del <classname
> per a fer possibles els filtres d'script. Els filtres poden subministrar un estri personalitzat que el &chalk; mostrarà a la galeria de filtres, el diàleg de previsualització de filtres o la pestanya d'opció d'eina de l'eina paint-with-filters. </para>
>Noteu que només la part esquerra d'aquest diàleg és de la vostra responsabilitat: el &chalk; té cura de la resta. Hi ha tres maneres de fer per a crear un estri d'opció: </para>
>Useu el &Qt; Designer per a crear una base d'estri, i feu-hi una subclasse per al vostre filtre</para
></listitem>
<listitem
><para
>Useu un dels estris simples que mostren un número de barres de desplaçament per a sencers per a llistes de sencers, dobles o bools. Aquests són útils si, com a la pantallada de dalt, el vostre filtre es poden configurar amb un número de sencers, dobles o bools. Mireu l'API dox per a <classname
>Picar a mà un estri. Això no està recomenat, i si ho feu i voleu que el vostre filtre formi part de la versió oficial del &chalk;, llavors us demanaré de reemplaçar-lo per un estri fet amb el &Qt; Designer.</para
list.insert(list.begin(), new KisOilPaintFilterConfiguration( 1, 30));
return list;
}
</programlisting>
<para
>Podeu veure com funciona: ompliu un vector amb els vostres paràmetres sencers i creeu l'estri. El mètode <methodname
>configuration()</methodname
> inspecciona l'estri i crea l'objecte de configuració de filtre adequat, en aquest cas, és clar, <classname
>KisOilPaintFilterConfiguration</classname
>. El mètode <methodname
>listOfExamplesConfiguration</methodname
> (que s'ha de reanomenar en correcte anglès...) retorna una llista amb objectes de configuració d'exemple per al diàleg de la galeria de filtres. </para>
>Hi ha més que codificar filtres interessants, és clar, però amb aquesta explicació, la documentació de l'API i l'accés al nostre codi font, hauríeu de ser capaços de començar. No dubteu a contactar els desenvolupador del &chalk; per IRC o a la llista de correu. </para>
>Les eines apareixen a la caixa d'eines del &chalk;. Això vol dir que hi ha un espai limitat per a noves eines, així que penseu bé quan una operació no és prou per als vostres propòsits. Les eines poden usar el ratolí/tauler i el teclat de maneres complexes, que les operacions de dibuix no poden. Aquesta és la raó per la qual Duplica és una eina, però esprai és una operació de dibuix. </para
>Aneu amb compte amb les dades estàtiques de la vostra eina: es crea una nova instància de la vostra eina per a cada dispositiu d'introducció: ratolí, stylus, esborrador, esprai i el que sigui. Les eines venen dividides en grups lògics: </para>
<itemizedlist>
<listitem
><para
>conforma eines de dibuix (cercle, rect)</para
></listitem>
<listitem
><para
>eines de dibuix a mà alçada (pinzell)</para
></listitem>
<listitem
><para
>Eines de transformació que desordenen la geometria de la capa</para
></listitem>
<listitem
><para
>eines d'ompliment (com omple galleda o gradient)</para
></listitem>
<listitem
><para
>eines de visualització (que no canvia els píxels, però altera la manera en què visualitzeu el llenç, com l'apropament/allunyament)</para
></listitem>
<listitem
><para
>eines de selecció (que canvien la màscara de selecció)</para
></listitem>
</itemizedlist>
<para
>La interfície d'eina es descriu a la documentació de l'API per a <classname
>KisTool</classname
>. Hi ha tres subclasses: <classname
>KisToolPaint</classname
>, <classname
>KisToolNonPaint</classname
> i <classname
>KisToolShape</classname
> (que de fet és una subclasse de <classname
>KisToolPaint</classname
>) que s'especialitza <classname
>KisTool</classname
> per a tasques de dibuix (és a dir, canviar els píxels) , les tasques que no són de dibuix i les tasques de forma de dibuix. </para
>Una eina té un estri d'opció, justament com els filtres. Actualment, els estris d'opció es mostren en una pestanya en una finestra flotant. Podem canviar a una banda sota el menú principal (que llavors reemplaça la barra d'eines) per al &chalk; 2.0, però per ara, dissenyeu el vostre estri d'opció per a encaixar en una pestanya. Com sempre, és millor usar el &Qt; Designer per al disseny de l'estri d'opció. </para
>El constructor arranja el nom intern "que no es tradueix" i la crida superclasse arranja el nom visible. També carreguem la imatge de cursor i arranja un munt de variables. </para>
>) els crida el &chalk; quan el dispositiu d'introducció (ratolí, stylus, esborrador, etc) es pressiona, es mou o es deixa anar. Noteu que també podeu obtenir esdeveniments de moviment si el botó del ratolí no està pressionat. Els esdeveniments no són els esdeveniments habituals de les &Qt;, sinó esdeveniments sintètics del &chalk; perquè fem ús de trucs de baix nivell per a obtenir prou esdeveniments com per a dibuixar una línia clara. Per omissió, els kits d'eines com les &Qt; (i les GTK) deixen anar esdeveniments si estan massa ocupades per a manegar-los, i nosaltres els volem tots. </para>
> és essencial: aquí creem l'acció que s'endollarà a la caixa d'eines per tal que els usuaris puguin seleccionar de fet l'eina. També assignem una tecla de drecera. Noteu que hi ha alguna codificació en marxa: recordeu que creem una instància de l'eina per a cada dispositiu d'entrada. Això també vol dir que cridem <methodname
>setup()</methodname
> per a cada dispositiu d'entrada i que vol dir que una acció amb el mateix nom s'afegeix moltes vegades a la col·lecció d'accions. Malgrat tot, tot sembla funcionar. Així que, per què preocupar-se? </para>
> es crida per a crear l'estri d'opció que el &chalk; mostrarà a l'eina. Ja que hi ha una eina per dispositiu d'entrada, l'estat d'una eina es pot mantenir a l'eina. Aquest mètode es crida només un cop: l'estri d'opció s'emmagatzema i es recupera el següent cop que l'eina s'activa. </para>
>Els PaintOps són un dels tipus d'endollables més innovadors del Chalk (juntament amb els d'espais de color). Una operació de dibuix defineis com les eies canvien els píxels que toquen. L'esprai, el lapis aliased o el pinzell de píxel antialiased: aquestes són totes operacions de dibuix. Però podeu (amb molta feina) crear un paintop que llegeixi les definicions de pinzell XML del Corel Painter i les usi per a determinar com s'ha fet un dibuix. </para
>Les operacions de dibuix s'inicien quan una eina de dibuix rep un esdeveniment de <literal
>mouseDown</literal
> i s'esborren quan rep l'esdeveniment mouseUp. Entre els dos, el paintop pot mantenir la traça de posicions prèvies i altres dades, com els nivells de pressió si l'usuari fa servir un tauler. </para
><para
>L'operació bàsica d'una operació de dibuix és canviar píxels a la posició del cursor d'una eina de dibuix. Això es pot fer només un cop, o aquesta pot demanar de ser usada a intervals regulars, usant un temporitzador. La primera pot ser útil per a un dibuix de tipus llapis, la segona, és clar, per a un paintop de tipus esprai. </para
>Els paintops poden tenir un petit estri de configuració que s'emplaça a la barra d'eines. Així, els estris de configuració dels paintops han de tenir format horitzontal d'estris que no siguin més alts que un botó de barra d'eines. Si no, el &chalk; tindrà un aspecte molt estrany. </para
>Anem a mirar un endollable simple de paintop, un que mostri una mica d'intel·ligència programàtica. Primer, al fitxer de capçalera, hi ha una factoria definida. Aquesta factoria crea un paintop quan l'eina activa en necessita un: </para>
> amb els noms privat i públic per al paintop (assegureu-vos que el vostre nom privat del paintop no col·lisiona amb un altre paintop!) i retornarà opcionalment un mapa de píxels. El &chalk; pot llavors mostrar el mapa de píxels jnut amb el nom per a la identificació visual del vostre paintop. Per exemple, un paintop de ganivet de pintor tindria la imatge d'aquesta implementació. </para
> és realment on ha de ser, amb els paintops. Aquest mètode rep dos paràmetres: la posició actual (que és en flotants, no en píxels sencers) i un objecte <classname
>KisPaintInformation</classname
> que conté la pressió, x i y, i el vector de moviment, i potser en el futur s'extengui amb altres informacions. </para>
<programlisting
>if (!m_painter->device()) return;
KisBrush *brush = m_painter->brush();
</programlisting>
<para
>Un <classname
>KisBrush</classname
> és la representació d'un fitxer de pinzell del Gimp: això és, una màscara, ja sigui una màscara simple o una sèrie de màscares. De fet, no usem el pinzell aquí, excepte per a determinar el <quote
// Split the coordinates into integer plus fractional parts. The integer
// is where the dab will be positioned and the fractional part determines
// the sub-pixel positioning.
Q_INT32 x, y;
double xFraction, yFraction;
splitCoordinate(pt.x(), &x, &xFraction);
splitCoordinate(pt.y(), &y, &yFraction);
KisPaintDeviceSP dab = new KisPaintDevice(colorSpace, "smeary dab");
Q_CHECK_PTR(dab);
</programlisting>
<para
>Nosaltres no canviem els píxels d'un dispositiu de dibuix directament: per comptes d'això, creeem un petit dispositiu de dibuix, un dab, i el composem al dispositiu de dibuix actual. </para>
<programlisting
>m_painter->setPressure(info.pressure);
</programlisting>
<para
>Com diuen els comentaris, el següent tros de codi fa alguna feina programàtica per a crear el dab real. En aquest cas, dibuixem un número de línies. Quan acabo amb aquest paintop, la llargada, la posició i el gruix de les línies dependrà de la pressió i de la càrrega de pintura, i haurem creat un pinzell a l'oli. Però no he tingut temps d'acabar-lo encara. </para>
<programlisting
>// Compute the position of the tufts. The tufts are arranged in a line
// perpendicular to the motion of the brush, i.e, the straight line between
// the current position and the previous position.
for (int i = 0; i < (NUMBER_OF_TUFTS / 2); ++i) {
// Compute the positions on the new vector.
vl = currentPointVector + i * brushVector;
KisPoint pl = vl.toKisPoint();
dab->setPixel(pl.roundX(), pl.roundY(), kc);
vr = currentPointVector - i * brushVector;
KisPoint pr = vr.toKisPoint();
dab->setPixel(pr.roundX(), pr.roundY(), kc);
}
vr = vr - vl;
vr.normalize();
</programlisting>
<para
>Finalment, hem construït el dab al dispositiu de dibuix original i hem dit al pintor que hem embrutat un petit rectangle al dispositiu de dibuix. </para>
<programlisting
>if (m_source->hasSelection()) {
m_painter->bltSelection(x - 32, y - 32, m_painter->compositeOp(), dab.data(),
m_source->selection(), m_painter->opacity(), x - 32, y -32, 64, 64);
}
else {
m_painter->bitBlt(x - 32, y - 32, m_painter->compositeOp(), dab.data(), m_painter->opacity(), x - 32, y -32, 64, 64);
}
m_painter->addDirtyRect(QRect(x -32, y -32, 64, 64));
>Això és tot: els paintops són fàcils i divertits! </para>
</sect2>
<sect2 id="developers-plugins-viewplugins">
<title
>Endollables de visualització</title>
<para
>Els endollables de visualització són els més estranys de tots:un endollable de visualització és una KPart ordinària que pot proveir una mica d'interfície d'usuari i alguna funcionalitat. Per exemple, la pestanya d'histograma és un endollable de visualització, així com el diàleg de rotació. </para>
>El &chalk; treballa amb l'arquitectura ordinària de filtres de fitxer del &koffice;. Hi ha un tutorial, una mica antic, però encara útil, a: <ulink url="http://koffice.org/developer/filters/oldfaq.php"
>. És probablement millor cooperar amb l'equip &chalk; quan es desenvolupin filtres de fitxer i fer el desenvolupament a l'arbre de filtres del &koffice;. Noteu que podeu provar els vostres filtres sense usar el &chalk; només usant la utilitat <command
>El gran problema amb els filtres d'importació és, naturalment, que el vostre codi llegeixi les dades del disc. L'important per a cridar aquest codi és prou simple: </para>
>Nota: de debò que hem de trobar una manera de fer que el &chalk; mantingui obert un fitxer i només llegeixei dades a mida que ho vagi necessitant, per comptes de copiar tots els continguts a la representació interna del dispositiu de dibuix. Però això voldria dir rerefons de gestió de dades que entenen els fitxers tiff i d'altres, i no estan actualment implementats. Seria ideal si alguns filtres de fitxer poguessin implementar una classe provisionalment anomenada <classname
>, creés un objecte d'aquesta instància amb el fitxer actual i el passés a KisDoc. Però el &chalk; manega l'emmagatzement per capa, no per document, de manera que això seria una bona feina per a fer.</para
>, perquè els documents del &chalk; necessiten un tractament especial. De fet, no seria pas una mala idea mirar si el resultat del repartiment no és 0, perquè si és així, la importació fallarà.</para
>Si cridem aquest filtre des de l'IGU, intentem obtenir la vista. Si hi ha una vista, el codi de conversió pot intentar actualitzar la barra de progrés.</para
></callout>
<callout arearefs="import4"
><para
>El filtre ens dóna el nom de fitxer per al fitxer d'entrada.</para
></callout>
<callout arearefs="import5"
><para
>Cal preparar el <classname
>KisDoc</classname
> per a la importació. Certs arranjaments s'inicialitzen i desfés està inhabilitat. D'altra manera, podríeu desfer l'afegiment de capes que fa el filtre d'importació i seria un comportament estrany.</para
></callout>
<callout arearefs="import6"
><para
>He escollit d'implementar el codi mateix d'importació en una classe separada que inicio aquí. També podeu introduir el vostre codi directament d'aquesta manera, però seria una mica brut.</para
></callout>
<callout arearefs="import7"
><para
>El meu importador retorna un codi d'estaurs que puc usar per a arranjar l'estatus del filtre d'importació. El &koffice; té cura de mostrar els missatges d'error.</para
></callout>
<callout arearefs="import8"
><para
>Si ha tingut èxit la creació del <classname
>KisImage</classname
>, arrangem la imatge actual del document a la nostra imatge creada ara mateix. Llavos ja estem: <literal