Archivo de 'software'

Tipos de posts personalizados en WordPress

WordPress es una maravilla de software. Nacido en 2003, actualmente es el gestor de contenidos más usado (53.9% de cuota de mercado). La clave de su éxito, en mi opinión, radica en su sencillez de uso, en su versatilidad, en ser un proyecto libre, y sobre todo en su comunidad de usuarios, que crean plugins para casi cualquier cosa que podamos imaginar.

¿Pero sabías que se pueden crear tipos de posts personalizados en los que alojar cualquier tipo de dato que se te ocurra?

Read more

Rutas en bici + Android

Hola :) Ahora que parece que el buen tiempo ha llegado para quedarse, es el momento de volver a coger la bici. Aprovechando mi nuevo teléfono, tengo la oportunidad de poder llevar un perfecto seguimiento de las rutas que hago.

Añadir rutas

Memorizar todos los caminos puede ser un poco complicado. Pero por suerte estos teléfonos traen GPS integrado. ¿Cómo podemos importar previamente nuestras rutas? Con Google Maps es muy sencillo. En primer lugar, definimos cómodamente la ruta en Google Earth desde nuestro PC:

Una vez definida la ruta, la guardamos a un fichero .kmz, pulsando sobre “Guardar lugar como…”

Ahora, desde Google Maps, y habiendo iniciado sesión con nuestra cuenta de Google, accedemos a “Mis mapas” > “Crear un mapa nuevo” > “Importar”, y seleccionamos el fichero .kmz. Establecemos un título y listo, ya tenemos la ruta lista para consultar en cualquier momento.

Ya desde Android, accedemos a Maps, pulsamos sobre el botón “Capas”, y desde ahí en “Más capas” > “Mis mapas”, podremos seleccionar cualquiera de nuestras rutas. ¡Y ya está! :) De esta forma ya no te perderás por los caminos.

Seguimientos

Existen muchas aplicaciones que realizan un seguimiento de los recorridos. Yo utilizo Endomondo, y me funciona de maravilla. De nuevo, mediante GPS, realiza un completo seguimiento del recorrido, velocidades, tiempos, realiza pausas automáticas, guarda un histórico, calorías quemadas, etc. Lo arrancas, y no es necesario que vuelvas a preocuparte hasta que finalices la ruta :) Por supuesto, sirve igualmente para recorridos a pie.

Destacaría de esta plataforma, respecto a otras, su facilidad de uso, la gran comunidad de usuarios que hay detrás, que es multiplataforma (Symbian, Android, iOs, Blackberry), altamente social y gratuito (pese a que existe una versión de pago por 2.95€).

Ahora que la batería de mi teléfono está cargada, me retiro. ¡Me espera una pequeña ruta de 20Km!

Edit. 10/04/2011 a las 19:48.
Soy un lila; hacía bastante viento (rachas de 45km/h), de modo que al final no he llegado a los 20Km. Pero como muestra de la utilidad de “compartir rutas” de Endomondo, aquí está mi práctica de hoy:

Y aquí las rachas de viento registradas hoy en el observatorio de Toledo:

Introducción a Doctrine 2

¡Hola! Últimamente sigo liado sumergiéndome en el mundo de ASP.NET, de ADO.NET, y sacando tiempo de debajo de las piedras para un pequeño proyecto en mi querido Zend Framework en PHP. Tras ver ADO.NET Entity Framework sentí la necesidad de usar algo igual en PHP; la solución se llama Doctrine :) La primera pregunta que nos deberíamos hacer es, qué es exactamente Doctrine. Respuesta rápida: Es un ORM de PHP. Pero analicémoslo un poco más.

En primer lugar, ¿qué diantres es un ORM? Viene de las siglas Object-relational mapping, que viene a traducirse como Mapeo objeto-relacional. En concreto es una técnica, o patrón arquitectónico, que permite comunicar dos sistemas distintos, típicamente una base de datos relacional con objetos de un lenguaje orientado a objetos, mediante un sistema que “mapea” (vincula) ambos sistemas. Mucha gente (yo mismo) ha creado a mano sus objetos mapeadores que, junto con objetos usando el patrón Active Record, daban un resultado muy similar a lo que un ORM nos ofrece. Pero oye, un ORM hace todo el trabajo sucio por nosotros ;)

Existen ORMs para la mayoría de lenguajes de programación. Por ejemplo, en Java es muy popular Hibernate, en .NET se utiliza ADO.NET Entity Framework, y en PHP el más usado es Doctrine (hay más). Doctrine está inspirado en Hibernate.

Pero veamos algunas de las características que nos ofrece un ORM como Doctrine 2:

  • Muy sencillo de configurar. De hecho, no es necesario mantener complejos ficheros de configuración XML.
  • Tiene su propio dialecto de SQL, llamado DQL (Doctrine Query Language).
  • Puede generar los modelos (las clases PHP que representan una fila de la BD) a partir de la base de datos. Sólo habría que definir las dependencias entre ellos
  • Del mismo modo, también puede generar la base de datos a partir de los modelos.

¡Fantástico! Él puede crear las tablas, y las consultas por nosotros. Pero veamos ahora lo sencillo que es usarlo:

/* Código de inicialización ... */
$user = new User();
$user->name = "john";
$user->password = "doe";
$em->persist($user);
$em->flush();

Para que este código funcione sólo tenemos que hacer dos cosas:

  1. Creamos el código de inicialización que cree el EntityManager $em. Es el objeto que en última instancia lleva a cabo las acciones.
  2. Definimos las entidades (módulos) especificando en comentarios (o en XML o en YAML) cómo se relaciona con la base de dato

Vamos a ver cómo instalarlo y después haremos un ejemplo sencillo en SQLite.

Instalación

Si bien podemos instalarlo a mano descargándolo desde la página de Doctrine, para esta guía asumiré que se ha instalado con PEAR. Para ello tenemos primer que instalar el canal:

sudo pear channel-discover pear.doctrine-project.org

Y después instalamos el ORM:

sudo pear install pear.doctrine-project.org/DoctrineORM-2.0.1

Ahora lo tenemos instalado. Podemos probar a ejecutar su utilidad de línea de comandos, y nos mostrará esto:

$ doctrine
Doctrine Command Line Interface version 2.0.1
Usage:
[options] command [arguments]
Options:
--help           -h Display this help message.
--quiet          -q Do not output any message.
--verbose        -v Increase verbosity of messages.
--version        -V Display this program version.
--ansi           -a Force ANSI output.
--no-interaction -n Do not ask any interactive question.
Available commands:
help                         Displays help for a command (?)
list                         Lists commands
dbal
:import                      Import SQL file(s) directly to Database.
:run-sql                     Executes arbitrary SQL directly from the command line.
orm
:convert-d1-schema           Converts Doctrine 1.X schema into a Doctrine 2.X schema.
:convert-mapping             Convert mapping information between supported formats.
:ensure-production-settings  Verify that Doctrine is properly configured for a production environment.
:generate-entities           Generate entity classes and method stubs from your mapping information.
:generate-proxies            Generates proxy classes for entity classes.
:generate-repositories       Generate repository classes from your mapping information.
:run-dql                     Executes arbitrary DQL directly from the command line.
:validate-schema             Validate that the mapping files.
orm:clear-cache
:metadata                    Clear all metadata cache of the various cache drivers.
:query                       Clear all query cache of the various cache drivers.
:result                      Clear result cache of the various cache drivers.
orm:schema-tool
:create                      Processes the schema and either create it directly on EntityManager Storage Connection or generate the SQL output.
:drop                        Drop the complete database schema of EntityManager Storage Connection or generate the corresponding SQL output.
:update                      Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.

Demo básica

Para este apartado, voy a utilizar una demo Sandbox (entorno de pruebas) prácticamente igual que la que usan en la documentación de Doctrine 2. En este artículo encontrarás el código de todos los ficheros necesarios. Además, al final del mismo encontrarás un enlace para poder descargarlo.

El proyecto consiste de sólo 4 ficheros:

  • Entities/Users.php – Modelo de usuarios
  • Entities/Address.php – Modelo de dirección
  • cli-config.php – Fichero PHP que contiene el código de inicialización necesario para usar la utilidad en linea de comandos ‘doctrine’. Cada vez que usemos la utilidad ‘doctrine’, tendremos que tener este fichero.
  • index.php – Código de inicialización típico de una aplicación web que utilice Doctrine 2.

Vamos a echar un vistazo a los ficheros. En primer lugar veamos cómo es el archivo cli-config.php:

<?php
// (1) Autocargamos clases
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();

// (2) Configuración
$config = new \Doctrine\ORM\Configuration();

// (3) Caché
$cache = new \Doctrine\Common\Cache\ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);

// (4) Driver
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
$config->setMetadataDriverImpl($driverImpl);

// (5) Proxies
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');

// (6) Conexión
$connectionOptions = array(
'driver' => 'pdo_sqlite',
'path' => 'database.sqlite'
);

// (7) EntityManager
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

// (8) HelperSet
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));

¡Que nadie se asuste! Realmente es un código muy sencillo, y prácticamente siempre se usará algo igual o muy parecido. Para superar el medio inicial, vamos a ver detalladamente qué es lo que ha pasado. El proceso de inicialización consta básicamente de dos pasos: Por una parte hay que asegurarse de que las clases de Doctrine pueden cargarse, y por otra hay que crear una instancia del Entity Manager. Siguiendo paso a paso:

  1. En primer lugar autocargamos las clases necesarias (nota: para esto podríamos haber utilizado el autocargador de otro framework). En concreto autocargaremos 3 secciones:
    1. El propio Doctrine, que trae Common, DBAL, ORM y Symfony. Si lo hemos instalado con PEAR, podremos verlo en el directorio /usr/share/php/Doctrine.
    2. Entities, que es el directorio en el que almacenaremos nuestros modelos.
    3. Proxies, otro espacio que es necesario definir. Los proxies son subclases de nuestros modelos que el propio Doctrine crea automáticamente.
  2. Una vez que nos hemos asegurado de que todas las clases pueden cargarse automáticamente, comenzamos a crear nuestro objeto EntityManager. Para ello, lo primero es crear un objeto de tipo Configuration.
  3. El primer parámetro que vamos a configurar es la caché. Podríamos haber usado APC, el sistema de cachés de facto de PHP (aconsejable en un entorno en producción), pero para pruebas usaremos el método ArrayCache.
  4. A continuación establecemos el driver con el que mapearemos nuestra base de datos. Esto es necesario para  hacer que nuestros modelos se correlacionen con nuestras bases de datos. Existen tres drivers disponibles:
    1. XML, desde donde se puede definir como encajar el modelo con la base de datos mediante sintaxis XML.
    2. YAML, al igual que con XML, también se puede definir utilizando YAML.
    3. Anotaciones, que en mi opinión son una maravilla. Mediante etiquetas en comentarios PHP defines cómo se mapean los datos. Más abajo, cuando lleguemos a los modelos, veremos un ejemplo de uso.
  5. Ahora configuramos los proxies. Simplemente establecemos su directorio, y su espacio de nombres.
  6. Conexión. Es aquí donde establecemos dónde se se encuentra nuestra base de datos. Si ésta no existiera, Doctrine la crearía por nosotros. En nuestro ejemplo usaremos SQLite.
  7. Ya está todo listo: hemos configurado la Caché, el Driver para mapear, los proxies y la conexión. Ya podemos crear el objeto EntityManager.
  8. Por último, creamos un objeto de tipo HelperSet, que es el que utilizará la utilidad de línea de comandos para saber cómo conectarse. El objeto HelperSet debe tener dos helpers: db, para identificar la conexión, y em, el EntityManager.

Ya tenemos listo el fichero cli-config.php, que como dijimos, es el que se utiliza para conectar la utilidad de consola ‘doctrine’ con nuestro proyecto.

Ahora vamos a ver los modelos.

Entities/Adress.php
<?php
namespace Entities;

/** @Entity @Table(name="addresses") */
class Address
{
   /**
    * @Id @Column(type="integer")
    * @GeneratedValue(strategy="AUTO")
    */
   private $id;

   /** @Column(type="string", length=255) */
   private $street;

   /** @OneToOne(targetEntity="User", mappedBy="address") */
   private $user;

   public function getId()
   {
      return $this->id;
   }

   public function getStreet()
   {
      return $this->street;
   }

   public function setStreet($street)
   {
      $this->street = $street;
   }

   public function getUser()
   {
      return $this->user;
   }

   public function setUser(User $user)
   {
      if ($this->user !== $user) {
         $this->user = $user;
         $user->setAddress($this);
      }
   }
}
Entities/User.php
<?php
namespace Entities;

/** @Entity @Table(name="users") */
class User
{
   /**
    * @Id @Column(type="integer")
    * @GeneratedValue(strategy="AUTO")
    */
   private $id;

   /** @Column(type="string", length=50) */
   private $name;

   /**
    * @OneToOne(targetEntity="Address", inversedBy="user")
    * @JoinColumn(name="address_id", referencedColumnName="id")
    */
   private $address;

   public function getId()
   {
      return $this->id;
   }

   public function getName()
   {
      return $this->name;
   }

   public function setName($name)
   {
      $this->name = $name;
   }

   public function getAddress()
   {
      return $this->address;
   }

   public function setAddress(Address $address)
   {
      if ($this->address !== $address) {
         $this->address = $address;
         $address->setUser($this);
      }
   }
}

No me detendré a explicar cómo se definen los modelos. En la propia documentación de Doctrine puedes ver una introducción al mapeo. Lo importante aquí es que, mediante etiquetas en los comentarios, hemos definido la relación entre la entidad User y la entidad Address, y también hemos definido cada una de sus columnas (¡hasta podemos indicar que una columna sea autoincremental!).

Llegados a este punto, tenemos 3 ficheros ya creados: cli-config.php, Entity/User.php y Entity/Address.php. Desde el raíz de nuestro proyecto vamos a ejecutar lo siguiente:

$ doctrine orm:schema-tool:create

Si todo ha ido bien, nos saldrá un mensaje indicándonos que el esquema de base de datos se ha creado correctamente. Y si comprobamos el directorio, veremos que se ha creado un nuevo fichero, database.sqlite, que contiene la definición de nuestras dos tablas.

Usándolo en una aplicación web

Bien, ya hemos definido las entidades, hemos creado la base de datos, y sabemos cómo funciona el código de inicialización de Doctrine 2. Ahora vamos a ver el fichero index.php:

<?php

// (1) Autocargamos clases
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', __DIR__);
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Proxies', __DIR__);
$classLoader->register();

// (2) Configuración
$config = new \Doctrine\ORM\Configuration();

// (3) Caché
$cache = new \Doctrine\Common\Cache\ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);

// (4) Driver
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
$config->setMetadataDriverImpl($driverImpl);

// (5) Proxies
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');

// (6) Conexión
$connectionOptions = array(
    'driver' => 'pdo_sqlite',
    'path' => 'database.sqlite'
);

// (7) EntityManager
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

// (8) Código de prueba
$user = new \Entities\User();
$address = new \Entities\Address();

echo 'Hola mundo!' . PHP_EOL;

// Introduce aquí el código que maneje $user y $address

Si nos fijamos, los 7 primeros puntos son exactamente iguales que en cli-config.php. En el punto 8 creamos dos objetos de nuestro modelo, ya listos para usar. ¡Pero cuidado! Antes de poder hacer cambios en la base de datos SQLite, debes asegúrate de que el usuario de tu servidor web tiene permisos de escritura en el fichero database.sqlite. Ahora podríamos añadir el siguiente código de ejemplo:

$address->setStreet("Calle Río tinto, 12");
$em->persist($address);
$em->flush();

echo "Insertamos dirección<br />" . PHP_EOL;

$user->setName("Pedro");
$user->setAddress($address);
$em->persist($user);
$em->flush();

echo "Insertamos usuario<br />" . PHP_EOL;

Simplemente tenemos que acceder desde nuestro navegador a ese fichero (o también mediante “php index.php”) para que PHP ejecute el código. Una vez hecho, podemos consultar la base de datos mediante sqlite3:

$ sqlite3 database.sqlite
SQLite version 3.6.22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from addresses;
1|Calle Río tinto, 12
sqlite> select * from users;
1|1|Pedro

¡Lo ha hecho todo él sólo por nosotros! Así de sencillo resulta trabajar con bases de datos con un ORM :) A partir de aquí empieza lo bueno: ya puedes guardar tus objetos de forma persistente en base de datos, sin tener preocuparte ni por crear las tablas, ni por SQL, ni nada. Céntrate en PHP :)

¡Gracias por leer!

Descargar el código fuente

CoRD, cliente de escritorio remoto de Mac

Hace unos días hablaba de mi reintroducción al mundo Windows. Para conectar desde Mac mencionaba que se podía utilizar el cliente de escritorio remoto de Microsoft. Bien, al poco de probarlo uno se da cuenta de que es un software que no está listo para producción. El teclado de un Mac es ligeramente distinto al de un Pc convencional. Una de las diferencias es que no tiene tecla “Alt Gr”. Si utilizas un teclado inglés de EEUU, esto no te supondrá un problema, ya que no se utiliza esa tecla:

Disposición de un teclado Inglés

Pero si ése no es tu caso, el cliente de escritorio remoto de Microsoft no te servirá; no hace una conversión previa de un teclado a otro, sino que envía a Windows tal cual las teclas que has pulsado.

Todo esto intenté antes de dar con la solución:

  • Utilizar otro software, como VNC.
  • Hacer uso de la combinación Alt+Ctrl, que en Windows emula la tecla AltGr. Además de ser incómodo, no muestra algunos caracteres como ‘{‘ o ‘\’.
  • Hacer un mapeo de teclado personalizado modificando el registro.

Cuando ya creía haberlo probado todo, vi un foro en el que hablaban de CoRD, un cliente de escritorio remoto para Windows. Lo probé, y a la primera :)

Además de contar con las mismas funcionalidades que el de Microsoft, tiene unas cuantas cosas que lo convierten en un mejor cliente RDP:

  • Se comporta mejor en el modo pantalla completa, ajustándolo a la resolución de tu monitor. Con el de Microsoft esto no ocurría, dejando una banda negra a cada lado.
  • Interpreta y convierte de tu teclado al equivalente en Windows. Puedes escribir la arroba, llaves, almohadillas, o corchetes.
  • Convierte la tecla cmd de Mac en la tecla Win.
  • Puedes tener varias sesiones abiertas a la vez, pudiendo navegar entre ellas desde un cómodo panel.

Y además, es open source!

Probando la Beta de IE9

Hace meses que en todo internet venimos hablando de la inminente salida de la próxima edición de Internet Explorer. Y el momento se acerca, pues hace a penas unos minutos Microsoft ha publicado en el IEBlog la liberación de la Beta de Internet Explorer 9. Está lista para descarga en la web

www.beautyoftheweb.com

En 33 lenguajes. Una gran noticia tanto para usuarios como para desarrolladores. Aunque todos esperamos que finalmente Microsoft recule y también permita instalarlo en Windows XP -hoy por hoy sigue siendo el sistema operativo más utilizado.

La instalación ha sido sencillísima; Desde la web BeautyOfTheWeb descargas el instalador, y éste se encarga de todo. Tras un reinicio, nuestro Windows ya está actualizado con IE9.

Nada más arrancarlo, detecta que hay numerosos addons que ralentizan el inicio del programa, de modo que nos muestra una ventana desde la que desactivar aquéllos que queramos, indicándonos también el tiempo que le toma a cada addon arrancar. Un detalle que se agradece mucho, y con el que estoy seguro que usuarios no avanzados sabrán maximizar el rendimiento de su navegador.

Una vez arrancado y listo para funcionar, nos encontramos con un navegador limpio, muy limpio. En mi opinión, más incluso que Google Chrome, puesto que en una sola fila localizamos:

  1. botones de avanzar y retroceder
  2. barra de navegación, con búsquedas, recargas, y detención.
  3. pestañas
  4. botones de inicio, favoritos y herramientas

Esto es todo :)

Compatibilidad con estándares

Pero lo primero es lo primero. Al comprobar el rendimiento de esta nueva versión con el conocido test Acid 3, esperaríamos conseguir un buen resultado cercano al 100. Pero eso no es así, obteniendo un 70:

Enorme FAIL, pero hay que entender que aun está en fase Beta y esto puede cambiar mucho en las próximas semanas.

Barra de navegación

Por lo demás, podemos comprobar cómo la barra de navegación es enormemente similar a la omnibar de Google Chrome, aunando buscador y barra de direcciones en uno, si bien se echa de menos prefijos de búsqueda como los que tenemos en Konqueror o en Chrome.

Gestor de descargas

Otras de las novedades que han sido desveladas ha sido el esperado gestor de descargas. Sencillo pero completo. Incluye una lista de los ficheros descargados, la localización, y las acciones posibles.

Developer Tools

De agradecer son estas herramientas, muy similares de nuevo a las de Google Chrome. Tenemos las siguientes secciones:

  • HTML
  • CSS
  • Consola
  • Script
  • Profiler (¡viva!)
  • Network

Otras consideraciones

Seguimos teniendo el botón de vista de compatibilidad. Personalmente lo veo innecesario, ya que al ser esta versión compatible con las anteriores, las páginas web específicas para una edición anterior podría hacer uso de las etiquetas meta destinadas al efecto.

Respecto a su limpieza, echo de más dos cosas: El botón “detener”, que bien podría ir junto al de refrescar, y el botón “página de inicio”.

Y en el menú de opciones podemos comprobar cómo no han innovado mucho, dando la sensación de volver al pasado al ser tan parecida a la de IE6

En resumen: Si bien se percibe en el rendimiento claramente que estamos ante una Beta, queda claro que Microsoft ha decidido no quedarse atrás. Una interfaz muy cuidada, un engine que promete, muy usable, y esperemos que ágil.

Google ya indexa SVG, mientras IE9 mejora su implementación

SVG, el estándar del w3c para gráficos vectoriales, está dando mucho de qué hablar. Hasta ahora su uso no ha sido muy extendido, e incluso muchos diseñadores y programadores web ni siquiera lo conocen. Es posible que esto cambie poco a poco.

Ejemplo en SVG

Estos días ha habido dos importantes novedades que seguro ayudarán a impulsar esta tecnología.

Google ahora indexa SVG

Por una parte, desde hoy Google indexa los ficheros SVG, tanto si está empotrado dentro de un documento HTML como si está en su propio fichero. Podemos ver ejemplos de cómo funcionan estas búsquedas: Ejemplo 1 y Ejemplo 2. De modo que ya cuentan con un tipo de fichero más a sumar a su extensa lista.

Una de las ventajas más evidentes es que esto impulsará el uso de SVG respecto a Flash. Recordemos que una de las principales funcionalidades de Flash es poder emplear gráficos vectoriales y animaciones en la web, cosa que también se puede realizar con SVG y JavaScript. Salvo que en el caso de Flash, la indexación de contenidos siempre ha sido bastante pobre. Esto con SVG parece que no pasará :)

IE9 se hace amigo de SVG

Y la segunda noticia viene de mano de Microsoft. Precisamente ayer publicaban en el IEBlog un artículo animándonos a que nos preparemos para SVG. A la vista de los resultados, han hecho una estupenda implementación de este estándar en su próximo navegador. Muestran además cómo se comporta, además de algunas pruebas en distintos navegadores.

Es de agradecer también que publiquen ejemplos de uso. No puedo evitar recordar mis inicios con la informática, cuando dibujaba polígonos en Basic o indagaba con la aplicación de renderizado 3d POV-Ray. Afortundamente, contamos con fantásticas aplicaciones para dibujar nuestros gráficos en SVG.

Recordemos que IE9 no saldrá hasta finales de 2010, a pesar de que este mes veremos la primera beta.