//---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 (Public License) // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // // Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3) // Pascal Port By: Milan Marusinec alias Milano // milan@marusinec.sk // http://www.aggpas.org // Copyright (c) 2005-2006 // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com // http://www.antigrain.com // //---------------------------------------------------------------------------- // // Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. // // [Pascal Port History] ----------------------------------------------------- // // 16.11.2005-Milano: Unit port establishment // { agg_color.pas } unit agg_color ; INTERFACE {$I agg_mode.inc } {$Q- } {$R- } uses Math , agg_basics ; { TYPES DEFINITION } type order_rgb = record R ,G ,B : byte end; order_bgr = record B ,G ,R : byte end; order_rgba = record R ,G ,B ,A : byte end; order_bgra = record B ,G ,R ,A : byte end; order_argb = record A ,R ,G ,B : byte end; order_abgr = record A ,B ,G ,R : byte end; order_type = record R ,G ,B ,A : int8u; end; const base_shift = 8; base_size = 1 shl base_shift; base_mask = base_size - 1; rgb_order : order_type = (R:0; G:1; B:2; A:3 ); bgr_order : order_type = (R:2; G:1; B:0; A:3 ); rgba_order : order_type = (R:0; G:1; B:2; A:3 ); bgra_order : order_type = (R:2; G:1; B:0; A:3 ); argb_order : order_type = (R:1; G:2; B:3; A:0 ); abgr_order : order_type = (R:3; G:2; B:1; A:0 ); type rgba8_ptr_ptr = ^rgba8_ptr; rgba8_ptr = ^rgba8; rgba8 = object r ,g ,b ,a : int8u; constructor Construct(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask ); procedure no_color; function gradient(c : rgba8; k : double ) : rgba8; end; aggclr_ptr = ^aggclr; aggclr = object v ,r ,g ,b ,a : int8u; constructor Construct; overload; constructor Construct(rgba : rgba8 ); overload; constructor Construct(clr : aggclr_ptr ); overload; constructor ConstrInt(v_ : unsigned; a_ : unsigned = base_mask ); overload; constructor ConstrInt(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask ); overload; constructor ConstrMix(r_ ,g_ ,b_ : unsigned; a_ : double = 1.0 ); constructor ConstrDbl(r_ ,g_ ,b_ : double; a_ : double = 1.0 ); constructor ConstrPre(r_ ,g_ ,b_ : double; a_ : double = 1.0 ); constructor from_wavelength(wl ,gamma : double ); function gradient (c : aggclr_ptr; k : double ) : aggclr; function gradient8(c : aggclr_ptr; k : double ) : rgba8; procedure add(c : aggclr_ptr; cover : unsigned ); function opacity_(a_ : double ) : aggclr_ptr; function _opacity : double; procedure clear; function premultiply : aggclr_ptr; procedure apply_gamma_dir(gamma_ : gamma_ptr ); end; { GLOBAL PROCEDURES } function rgb8_packed (v : unsigned ) : rgba8; IMPLEMENTATION { LOCAL VARIABLES & CONSTANTS } { UNIT IMPLEMENTATION } { CONSTRUCT } constructor rgba8.Construct; begin b{*}:=int8u(r_ ); g:=int8u(g_ ); r:=int8u(b_ ); a:=int8u(a_ ); end; { NO_COLOR } procedure rgba8.no_color; begin r:=0; g:=0; b:=0; a:=0; end; { GRADIENT } function rgba8.gradient(c : rgba8; k : double ) : rgba8; var ik : int32u; // calc_type begin ik:=Trunc(k * base_size ); result.r:=int8u(int32u(r ) + (((int32u(c.r ) - r ) * ik ) shr base_shift ) ); result.g:=int8u(int32u(g ) + (((int32u(c.g ) - g ) * ik ) shr base_shift ) ); result.b:=int8u(int32u(b ) + (((int32u(c.b ) - b ) * ik ) shr base_shift ) ); result.a:=int8u(int32u(a ) + (((int32u(c.a ) - a ) * ik ) shr base_shift ) ); end; { CONSTRUCT } constructor aggclr.Construct; begin v:=0; r:=0; g:=0; b:=0; a:=0; end; { CONSTRUCT } constructor aggclr.Construct(rgba : rgba8 ); begin v:=(rgba.r * 77 + rgba.g * 150 + rgba.b * 29 ) shr 8; r:=rgba.r; g:=rgba.g; b:=rgba.b; a:=rgba.a; end; { CONSTRUCT } constructor aggclr.Construct(clr : aggclr_ptr ); begin v:=clr.v; r:=clr.r; g:=clr.g; b:=clr.b; a:=clr.a; end; { CONSTRINT } constructor aggclr.ConstrInt(v_ : unsigned; a_ : unsigned = base_mask ); begin v:=int8u(v_ ); r:=0; g:=0; b:=0; a:=int8u(a_ ); end; { CONSTRINT } constructor aggclr.ConstrInt(r_ ,g_ ,b_ : unsigned; a_ : unsigned = base_mask ); begin v:=(r_ * 77 + g_ * 150 + b_ * 29 ) shr 8; r:=int8u(r_ ); g:=int8u(g_ ); b:=int8u(b_ ); a:=int8u(a_ ); end; { CONSTRDBL } constructor aggclr.ConstrDbl; begin v:=trunc((0.299 * r_ + 0.587 * g_ + 0.114 * b_ ) * base_mask + 0.5 ); r:=trunc(r_ * base_mask + 0.5 ); g:=trunc(g_ * base_mask + 0.5 ); b:=trunc(b_ * base_mask + 0.5 ); a:=trunc(a_ * base_mask + 0.5 ); end; { CONSTRPRE } constructor aggclr.ConstrPre; begin r_:=r_ * a_; g_:=g_ * a_; b_:=b_ * a_; ConstrDbl(r_ ,g_ ,b_ ,a_ ); end; { CONSTRMIX } constructor aggclr.ConstrMix; begin v:=(r_ * 77 + g_ * 150 + b_ * 29 ) shr 8; r:=r_; g:=g_; b:=b_; a:=trunc(a_ * base_mask + 0.5 ); end; { FROM_WAVELENGTH } constructor aggclr.from_wavelength(wl ,gamma : double ); var tr ,tg ,tb ,s : double; begin tr:=0; tg:=0; tb:=0; if (wl >= 380.0 ) and (wl <= 440.0 ) then begin tr:=-1.0 * (wl - 440.0 ) / (440.0 - 380.0 ); tb:=1.0; end else if (wl >= 440.0 ) and (wl <= 490.0 ) then begin tg:=(wl - 440.0 ) / (490.0 - 440.0 ); tb:=1.0; end else if (wl >= 490.0 ) and (wl <= 510.0 ) then begin tg:=1.0; tb:=-1.0 * (wl - 510.0 ) / (510.0 - 490.0 ); end else if (wl >= 510.0 ) and (wl <= 580.0 ) then begin tr:=(wl - 510.0 ) / (580.0 - 510.0 ); tg:=1.0; end else if (wl >= 580.0 ) and (wl <= 645.0 ) then begin tr:=1.0; tg:=-1.0 * (wl - 645.0 ) / (645.0 - 580.0 ); end else if (wl >= 645.0 ) and (wl <= 780.0 ) then tr:=1.0; s:=1.0; if wl > 700.0 then s:=0.3 + 0.7 * (780.0 - wl ) / (780.0 - 700.0 ) else if wl < 420.0 then s:=0.3 + 0.7 * (wl - 380.0 ) / (420.0 - 380.0 ); tr:=Power(tr * s ,gamma ); tg:=Power(tg * s ,gamma ); tb:=Power(tb * s ,gamma ); ConstrDbl(tr ,tg ,tb ); end; { GRADIENT } function aggclr.gradient; var ik : unsigned; begin ik:=trunc(k * base_size ); result.r:=int8u(r + (((c.r - r ) * ik ) shr base_shift ) ); result.g:=int8u(g + (((c.g - g ) * ik ) shr base_shift ) ); result.b:=int8u(b + (((c.b - b ) * ik ) shr base_shift ) ); result.a:=int8u(a + (((c.a - a ) * ik ) shr base_shift ) ); end; { GRADIENT8 } function aggclr.gradient8; var ik : unsigned; begin ik:=trunc(k * base_size ); result.r:=int8u(r + (((c.r - r ) * ik ) shr base_shift ) ); result.g:=int8u(g + (((c.g - g ) * ik ) shr base_shift ) ); result.b:=int8u(b + (((c.b - b ) * ik ) shr base_shift ) ); result.a:=int8u(a + (((c.a - a ) * ik ) shr base_shift ) ); end; { ADD } procedure aggclr.add(c : aggclr_ptr; cover : unsigned ); var cv ,cr ,cg ,cb ,ca : int32u; begin if cover = cover_mask then if c.a = base_mask then Construct(c ) else begin cv:=v + c.v; if cv > int32u(base_mask ) then v:=int8u(base_mask ) else v:=int8u(cv ); cr:=r + c.r; if cr > int32u(base_mask ) then r:=int8u(base_mask ) else r:=int8u(cr ); cg:=g + c.g; if cg > int32u(base_mask ) then g:=int8u(base_mask ) else g:=int8u(cg ); cb:=b + c.b; if cb > int32u(base_mask ) then b:=int8u(base_mask ) else b:=int8u(cb ); ca:=a + c.a; if ca > int32u(base_mask ) then a:=int8u(base_mask ) else a:=int8u(ca ); end else begin cv:=v + ((c.v * cover + cover_mask div 2 ) shr cover_shift ); cr:=r + ((c.r * cover + cover_mask div 2 ) shr cover_shift ); cg:=g + ((c.g * cover + cover_mask div 2 ) shr cover_shift ); cb:=b + ((c.b * cover + cover_mask div 2 ) shr cover_shift ); ca:=a + ((c.a * cover + cover_mask div 2 ) shr cover_shift ); if cv > int32u(base_mask ) then v:=int8u(base_mask ) else v:=int8u(cv ); if cr > int32u(base_mask ) then r:=int8u(base_mask ) else r:=int8u(cr ); if cg > int32u(base_mask ) then g:=int8u(base_mask ) else g:=int8u(cg ); if cb > int32u(base_mask ) then b:=int8u(base_mask ) else b:=int8u(cb ); if ca > int32u(base_mask ) then a:=int8u(base_mask ) else a:=int8u(ca ); end; end; { OPACITY_ } function aggclr.opacity_; begin if a_ < 0.0 then a_:=0.0; if a_ > 1.0 then a_:=1.0; a:=trunc(a_ * base_mask + 0.5 ); result:=@self; end; { _OPACITY } function aggclr._opacity; begin result:=a / base_mask; end; { CLEAR } procedure aggclr.clear; begin v:=0; r:=0; g:=0; b:=0; a:=0; end; { PREMULTIPLY } function aggclr.premultiply : aggclr_ptr; begin if a = base_mask then begin result:=@self; exit; end; if a = 0 then begin v:=0; r:=0; g:=0; b:=0; result:=@self; exit; end; v:=int8u((v * a ) shr base_shift ); r:=int8u((r * a ) shr base_shift ); g:=int8u((g * a ) shr base_shift ); b:=int8u((b * a ) shr base_shift ); end; { APPLY_GAMMA_DIR } procedure aggclr.apply_gamma_dir; begin v:=int8u(gamma_.dir(v ) ); r:=int8u(gamma_.dir(r ) ); g:=int8u(gamma_.dir(g ) ); b:=int8u(gamma_.dir(b ) ); end; { RGB8_PACKED } function rgb8_packed; begin result.r:=(v shr 16) and $FF; result.g:=(v shr 8) and $FF; result.b:=v and $FF; result.a:=base_mask; end; END. {*}