Nach langem überlegen, wie man Farbtags am besten implementiert, so dass es einen guten Kompromiss aus Vielfaltigkeit und Kürze gibt, bin ich auf folgende Idee gekommen: Der HSL-Farbraum (der in CSS3 übrigens auch angewendet werden kann) unterteilt sich in die Parameter Farbe, Sättigung und Licht. Das hat den Vorteil gegenüber RGB, dass man die Farbe gezielt wählen kann - und dann erst manipulieren kann/muss.
Beim überlegen der Syntax bin ich eher zufällig als absichtlich auf das Zeichen @ gestossen - im RP wirds nicht gebraucht und hat auch sonst keine Sonderbedeutung. Damit man sich auch keine hunderte Symbole merken muss, habe ich ein System geschaffen, das 4-Stellig ist und 3468 Farben umfasst - müsste wohl genug sein.
Der Vorteil dieses Systems ist, dass die 3468 Farben ohne irgendwelche Datenbanken verfügbar sind, Farbtags müssen nichtmehr hinzugefügt werden. Der grosse Nachteil ist, dass sich der Speicherbedarf gut verdoppelt für die Farbtags, heisst also, die Felder für Namen und so müssen weiterwachsen... Ein Name mit 50 Zeichen benötigt genau 255 Zeichen Platz mit Schliessfarbe, um jeden Buchstaben einzeln färben zu können.
Um nun zur Syntax zu kommen: Die Syntax der Farbtags funktioniert so:
$this->bbcode_second_pass_code('', '@<Farbe><Sättigung><Intensität>')
Farbe ist dabei ein Zeichen zwischen 0 und 9, A oder B, wobei A für 10 und B für 11 steht. 0 ist Rot, 1 Orange, 2 Gelb, 4 Grün, 6 Cyan, 8 Blau und A Magenta - 9 ist zum Beispiel Blau-Magenta, also Violett.
Sättigung ist ein Zeichen zwischen 0 und 9, A und H. 0-F entsprechen den Hexadezimalzahlen, G steht für 16, H für 17 - diese Wahl musste ich treffen um die Schritte schön gestalten zu können.
Die Lichtintensität folgt der Sättigung mit den selben Zeichen.
Zusätzlich gibt es noch für die Sättung und die Intensität die Synonyme @. Bei der Sättigung steht @ für 100%-ige Sättiung, also H. Eine Intensität von "@" bedeutet halbe Lichtintensität, also zwischen ganz-dunkel und ganz-hell, was dem normalen Farbton entspricht. Das W3
hat gute Tabellen für den HSL-Farbraum.
Mit @@@@ schliesst man den Farbtag (`0), mit @@ schreibt man ein normales @ (wie ``).
Einige Beispiele:
$this->bbcode_second_pass_code('', '@0@@ => rgb(255, 0, 0)
@2@@ => rgb(255, 255, 0)
@4@@ => rgb(0, 255, 0)
@000 => rgb(0, 0, 0)
@0G0 => rgb(0, 0, 0)
@0HH => rgb(255, 255, 255)
@8D4 => rgb(6%, 6%, 43%), Dunkles Cyan-Blau')
$this->bbcode_second_pass_code('', '<?php
/**
* exCT: Extended Colortags. Erweiterte Farbtags für LoGD
*
* @author Basilius Sauter
* @copyright 2009
* @version 0.1
* @package exct
*
*/
class ExCT {
const SIGN_HSL = '@';
# Umwandlungstabelle Farbcode => Farbe im HSL-Farbrau
protected $keyA = array(
'0' => 000, # Rot
'1' => 030, # Orange
'2' => 060, # Gelb
'3' => 090, # Grün-Gelb
'4' => 120, # Grün
'5' => 150, # Grün-Cyan
'6' => 180, # Cyan
'7' => 210, # Cyan-Blau
'8' => 240, # Blau
'9' => 270, # Blau-Magenta
'A' => 300, # Magenta
'B' => 330, # Magenta-Rot
);
# Umwandlungstabelle Farbcode => Sättigung (Saturation, S) oder Farbintensität
protected $keyB = array(
'0' => 0.00, '1' => 0.0625,
'2' => 0.125, '3' => 0.1875,
'4' => 0.25, '5' => 0.3125,
'6' => 0.375, '8' => 0.4375,
'9' => 0.5, 'A' => 0.5625,
'B' => 0.625, 'C' => 0.6825,
'D' => 0.75, 'E' => 0.8125,
'F' => 0.875, 'G' => 0.9375,
'H' => 1,
);
protected static $instance = false;
protected function __construct() {
}
public function getInstance() {
if(self::$instance === false) {
self::$instance = new self();
}
return self::$instance;
}
public function stripTags($data) {
$striptmpl = '/[%s].../';
$data = preg_replace(sprintf($striptmpl, preg_quote(self::SIGN_HSL)), '', $data);
$data = str_replace('@@', '', $data);
return $data;
}
public function parseTags($data) {
$parsed = '';
$opentag = false;
while( (!(($x = strpos($data, '@')) === false)) ) {
$tag = substr($data, $x, 1);
# Einzelne Farben holen
$tag_r = strtoupper(substr($data, $x+1, 1));
$tag_g = strtoupper(substr($data, $x+2, 1));
$tag_b = strtoupper(substr($data, $x+3, 1));
# Alles, was bis zum Farbsymbol steht, parsed zuteilen
$parsed .= substr($data, 0, $x);
# Von $data alles abschneiden, was schon geparst wurde, inklusive Farbtag
if($tag_r == '@' AND ($tag_g != '@' OR $tag_b != '@')) {
$nocolor = true;
$data = substr($data, $x+2);
}
else {
$nocolor = false;
$data = substr($data, $x+4);
}
if(($tag_r == '@' AND $tag_g == '@' AND $tag_b == '@') AND $nocolor === false) {
if($opentag === true) {
$parsed .= '</span>';
$opentag = false;
}
}
elseif($nocolor) {
$parsed .= '@';
}
else {
# Alias für Sättigung = 100%
if($tag_g == '@') $tag_g = 'H';
# Alias für Lichtintensität = 50%
if($tag_b == '@') $tag_b = '9';
var_dump( $tag_r, $tag_g, $tag_b );
$col_h = $this->keyA[$tag_r];
$col_s = $this->keyB[$tag_g];
$col_l = $this->keyB[$tag_b];
$cols = $this->hsl2rgb($col_h, $col_s, $col_l, true, true);
$col_r = $cols[0];
$col_g = $cols[1];
$col_b = $cols[2];
if($opentag) $parsed .= '</span>';
else $opentag = true;
$parsed .= sprintf('<span style="color: rgb(%d%%, %d%%, %d%%) /*hsl(%f, %f, %f)*/">',
$col_r*100, $col_g*100, $col_b*100,
$col_h, $col_s, $col_l
);
}
}
# Der übrig gebliebene Rest hinzufügen
$parsed .= $data;
return $parsed;
}
# HSL 2 RGB, nach W3
public function hsl2rgb($h, $s, $l, $return = true, $degree = false) {
if($l < 0.5) {
$m2 = $l * (1 + $s);
}
else {
$m2 = $l + $s - ($l * $s);
}
$m1 = 2 * $l - $m2;
if($degree === true) {
$h = $h/360;
}
$r = $this->hue2rgb($m1, $m2, $h+1/3);
$g = $this->hue2rgb($m1, $m2, $h);
$b = $this->hue2rgb($m1, $m2, $h-1/3);
if($return === true) {
return array($r, $g, $b);
}
else {
switch($return) {
case 'r': return $r; break;
case 'g': return $g; break;
case 'b': return $b; break;
}
}
}
# HUE 2 RGB, nach W3, Hilfsfunktion für hsl2rgb()
public function hue2rgb($m1, $m2, $h) {
if($h < 0) $h = $h+1;
if($h > 1) $h = $h-1;
if($h*6 < 1) return $m1+($m2-$m1)*$h*6;
if($h*2 < 1) return $m2;
if($h*3 < 2) return $m1+($m2-$m1)*(2/3-$h)*6;
return $m1;
}
}
?>')
Die Anwendung der Klasse ist relativ einfach:
$this->bbcode_second_pass_code('', '$exCT = exCT::getInstance();
$data = $exCT->parseTags("@0@@Rote Farbe @0D4Dunkelrote Farbe");')