2 Cockos WDL - LICE - Lightweight Image Compositing Engine
3 Copyright (C) 2007 and later, Cockos Incorporated
4 File: lice.cpp (LICE core processing)
5 See lice.h for license and other information
9 #ifndef __LICE_CPP_IMPLEMENTED__
10 #define __LICE_CPP_IMPLEMENTED__
14 #include <stdio.h> // only included in case we need to debug with sprintf etc
16 #include "lice_combine.h"
17 #include "lice_extended.h"
20 #include "../swell/swell.h"
23 _LICE_ImageLoader_rec
*LICE_ImageLoader_list
;
25 LICE_pixel
LICE_CombinePixels(LICE_pixel dest
, LICE_pixel src
, float alpha
, int mode
)
27 int r
= LICE_GETR(src
);
28 int g
= LICE_GETG(src
);
29 int b
= LICE_GETB(src
);
30 int a
= LICE_GETA(src
);
31 int al
= (int)(alpha
*256.0f
);
33 #define __LICE__ACTION(COMBFUNC) COMBFUNC::doPix((LICE_pixel_chan*)&dest,r, g, b, a, al)
34 __LICE_ACTION_SRCALPHA(mode
, al
,false);
41 void LICE_CombinePixels2(LICE_pixel
*destptr
, int r
, int g
, int b
, int a
, int ia
, int mode
)
43 #define __LICE__ACTION(COMBFUNC) COMBFUNC::doPix((LICE_pixel_chan*)destptr,r, g, b, a, ia)
44 __LICE_ACTION_SRCALPHA(mode
, ia
, false);
47 void LICE_CombinePixels2Clamp(LICE_pixel
*destptr
, int r
, int g
, int b
, int a
, int ia
, int mode
)
49 #define __LICE__ACTION(COMBFUNC) COMBFUNC::doPix((LICE_pixel_chan*)destptr,r, g, b, a, ia)
50 __LICE_ACTION_SRCALPHA(mode
, ia
, true);
55 LICE_MemBitmap::LICE_MemBitmap(int w
, int h
, unsigned int linealign
)
61 m_linealign
= linealign
> 1 ? ((linealign
& ~(linealign
-1))-1) : 0; // force to be contiguous bits
62 if (m_linealign
>16) m_linealign
=16;
63 if (w
>0&&h
>0) resize(w
,h
);
66 LICE_MemBitmap::~LICE_MemBitmap() { free(m_fb
); }
68 bool LICE_MemBitmap::resize(int w
, int h
)
70 if (w
!=m_width
||h
!=m_height
)
72 #ifdef DEBUG_TIGHT_ALLOC // dont enable for anything you want to be even remotely fast
74 m_fb
= (LICE_pixel
*)malloc((m_allocsize
= ((w
+m_linealign
)&~m_linealign
)*h
*sizeof(LICE_pixel
)) + LICE_MEMBITMAP_ALIGNAMT
);
79 int sz
=(((m_width
=w
)+m_linealign
)&~m_linealign
)*(m_height
=h
)*sizeof(LICE_pixel
);
81 if (sz
<=0||w
<1||h
<1) { free(m_fb
); m_fb
=0; m_allocsize
=0; }
82 else if (!m_fb
) m_fb
=(LICE_pixel
*)malloc((m_allocsize
=sz
) + LICE_MEMBITMAP_ALIGNAMT
);
88 if (!(m_fb
=(LICE_pixel
*)realloc(m_fb
,(m_allocsize
=sz
+sz
/4)+LICE_MEMBITMAP_ALIGNAMT
)))
91 m_fb
=(LICE_pixel
*)malloc((m_allocsize
=sz
)+LICE_MEMBITMAP_ALIGNAMT
);
95 if (!m_fb
) {m_width
=m_height
=0; }
104 #ifndef _LICE_NO_SYSBITMAPS_
106 LICE_SysBitmap::LICE_SysBitmap(int w
, int h
)
110 m_dc
= CreateCompatibleDC(NULL
);
123 LICE_SysBitmap::~LICE_SysBitmap()
126 if (m_oldbitmap
&& m_dc
) SelectObject(m_dc
,m_oldbitmap
);
127 if (m_bitmap
) DeleteObject(m_bitmap
);
128 if (m_dc
) DeleteDC(m_dc
);
131 SWELL_DeleteGfxContext(m_dc
);
135 bool LICE_SysBitmap::resize(int w
, int h
)
138 if (!m_dc
) { m_width
=m_height
=0; m_bits
=0; return false; }
141 if (m_width
==w
&& m_height
== h
) return false;
146 #ifndef DEBUG_TIGHT_ALLOC
147 // dont resize down bitmaps
148 if (w
&& h
&& w
<= m_allocw
&& h
<= m_alloch
&& m_bits
)
153 m_bits
=(LICE_pixel
*)SWELL_GetCtxFrameBuffer(m_dc
);
154 m_bits
+= (m_alloch
-h
)*m_allocw
;
159 #endif//!DEBUG_TIGHT_ALLOC
161 w
= (w
+3)&~3; // always keep backing store a multiple of 4px wide
170 SelectObject(m_dc
,m_oldbitmap
);
173 if (m_bitmap
) DeleteObject(m_bitmap
);
178 if (w
<1 || h
<1) return false;
180 BITMAPINFO pbmInfo
= {0,};
181 pbmInfo
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
182 pbmInfo
.bmiHeader
.biWidth
= w
;
183 pbmInfo
.bmiHeader
.biHeight
= isFlipped()?h
:-h
;
184 pbmInfo
.bmiHeader
.biPlanes
= 1;
185 pbmInfo
.bmiHeader
.biBitCount
= sizeof(LICE_pixel
)*8;
186 pbmInfo
.bmiHeader
.biCompression
= BI_RGB
;
187 m_bitmap
= CreateDIBSection( NULL
, &pbmInfo
, DIB_RGB_COLORS
, (void **)&m_bits
, NULL
, 0);
189 if (m_bitmap
) m_oldbitmap
=SelectObject(m_dc
, m_bitmap
);
190 else { m_width
=m_height
=0; m_bits
=0; }
192 if (m_dc
) SWELL_DeleteGfxContext(m_dc
);
196 if (w
<1 || h
<1) return false;
198 m_dc
=SWELL_CreateMemContext(0,w
,h
);
199 if (!m_dc
) { m_width
=m_height
=0; m_bits
=0; }
200 else m_bits
=(LICE_pixel
*)SWELL_GetCtxFrameBuffer(m_dc
);
206 #endif // _LICE_NO_SYSBITMAPS_
210 #ifndef LICE_NO_BLIT_SUPPORT
211 void LICE_Copy(LICE_IBitmap
*dest
, LICE_IBitmap
*src
) // resizes dest
215 dest
->resize(src
->getWidth(),src
->getHeight());
216 LICE_Blit(dest
,src
,0,0,NULL
,1.0,LICE_BLIT_MODE_COPY
);
221 template<class COMBFUNC
> class _LICE_Template_Blit0
// these always templated
224 static void solidBlitFAST(LICE_pixel
*dest
, int w
, int h
,
230 LICE_pixel
*pout
=dest
;
234 COMBFUNC::doPixFAST(pout
,color
);
243 static void scaleBlitFAST(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
,
244 int icurx
, int icury
, int idx
, int idy
, unsigned int clipright
, unsigned int clipbottom
,
245 int src_span
, int dest_span
)
247 LICE_pixel
* destpx
= (LICE_pixel
*) dest
;
248 int destpxspan
= dest_span
*(int)sizeof(LICE_pixel_chan
)/(int)sizeof(LICE_pixel
);
252 const unsigned int cury
= icury
>> 16;
253 if (cury
< clipbottom
)
256 const LICE_pixel_chan
*inptr
=src
+ cury
* src_span
;
257 LICE_pixel
* pout
= destpx
;
261 const unsigned int offs
=curx
>> 16;
264 COMBFUNC::doPixFAST(pout
,((LICE_pixel
*)inptr
)[offs
]);
271 destpx
+= destpxspan
;
278 #ifndef LICE_FAVOR_SIZE_EXTREME
279 template<class COMBFUNC
>
281 class _LICE_Template_Blit1
// these controlled by LICE_FAVOR_SIZE_EXTREME
283 #ifdef LICE_FAVOR_SIZE_EXTREME
284 #define DOPIX(pout,r,g,b,a,ia) combFunc(pout,r,g,b,a,ia);
286 #define DOPIX(pout,r,g,b,a,ia) COMBFUNC::doPix(pout,r,g,b,a,ia);
289 static void solidBlit(LICE_pixel_chan
*dest
, int w
, int h
,
290 int ir
, int ig
, int ib
, int ia
,
292 #ifdef LICE_FAVOR_SIZE_EXTREME
293 , LICE_COMBINEFUNC combFunc
299 LICE_pixel_chan
*pout
=dest
;
303 DOPIX(pout
,ir
,ig
,ib
,ia
,ia
);
304 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
309 static void gradBlit(LICE_pixel_chan
*dest
, int w
, int h
,
310 int ir
, int ig
, int ib
, int ia
,
311 int drdx
, int dgdx
, int dbdx
, int dadx
,
312 int drdy
, int dgdy
, int dbdy
, int dady
,
314 #ifdef LICE_FAVOR_SIZE_EXTREME
315 , LICE_COMBINEFUNC combFunc
321 int r
=ir
,g
=ig
,b
=ib
,a
=ia
;
322 ir
+=drdy
; ig
+=dgdy
; ib
+=dbdy
; ia
+=dady
;
323 LICE_pixel_chan
*pout
=dest
;
328 DOPIX(pout
,r
/65536,g
/65536,b
/65536,ia
,ia
);
329 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
330 r
+=drdx
; g
+=dgdx
; b
+=dbdx
; a
+=dadx
;
340 #ifndef LICE_FAVOR_SIZE
341 template<class COMBFUNC
>
343 class _LICE_Template_Blit2
// these controlled by LICE_FAVOR_SIZE
345 #ifdef LICE_FAVOR_SIZE
346 #define DOPIX(pout,r,g,b,a,ia) combFunc(pout,r,g,b,a,ia);
348 #define DOPIX(pout,r,g,b,a,ia) COMBFUNC::doPix(pout,r,g,b,a,ia);
353 static void blit(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
, int src_span
, int dest_span
, int ia
354 #ifdef LICE_FAVOR_SIZE
355 , LICE_COMBINEFUNC combFunc
362 const LICE_pixel_chan
*pin
=src
;
363 LICE_pixel_chan
*pout
=dest
;
367 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],ia
);
369 pin
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
370 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
377 // this is only designed for filtering down an image approx 2:1 to 4:1 or so.. it'll work (poortly) for higher, and for less it's crap too.
378 // probably need to redo it using linear interpolation of the filter coefficients, but bleh I'm gonna go play some call of duty
379 static void scaleBlitFilterDown(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
,
380 int icurx
, int icury
, int idx
, int idy
, int clipright
, int clipbottom
,
381 int src_span
, int dest_span
, int ia
, const int *filter
, int filt_start
, int filtsz
382 #ifdef LICE_FAVOR_SIZE
383 , LICE_COMBINEFUNC combFunc
391 int cury
= icury
>> 16;
394 if (cury
>= 0 && cury
< clipbottom
)
396 const LICE_pixel_chan
*inptr
=src
+ (cury
+filt_start
) * src_span
;
397 LICE_pixel_chan
*pout
=dest
;
401 if (offs
>=0 && offs
<clipright
)
406 int ypos
=cury
+filt_start
;
407 const LICE_pixel_chan
*rdptr
= inptr
+ (offs
+ filt_start
)*(int) (sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
));
408 const int *scaletab
= filter
;
411 if (ypos
>= clipbottom
) break;
415 int xpos
=offs
+ filt_start
;
416 const LICE_pixel_chan
*pin
= rdptr
;
420 int tsc
= *scaletab
++;
421 if (xpos
>= 0 && xpos
< clipright
)
423 r
+=pin
[LICE_PIXEL_R
]*tsc
;
424 g
+=pin
[LICE_PIXEL_G
]*tsc
;
425 b
+=pin
[LICE_PIXEL_B
]*tsc
;
426 a
+=pin
[LICE_PIXEL_A
]*tsc
;
430 pin
+=sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
433 else scaletab
+= filtsz
;
440 DOPIX(pout
,r
/sc
,g
/sc
,b
/sc
,a
/sc
,ia
);
444 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
452 static void scaleBlit(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
,
453 int icurx
, int icury
, int idx
, int idy
, unsigned int clipright
, unsigned int clipbottom
,
454 int src_span
, int dest_span
, int ia
, int filtermode
455 #ifdef LICE_FAVOR_SIZE
456 , LICE_COMBINEFUNC combFunc
462 if (filtermode
== LICE_BLIT_FILTER_BILINEAR
)
466 const unsigned int cury
= icury
>> 16;
467 const int yfrac
=icury
&65535;
469 const LICE_pixel_chan
*inptr
=src
+ cury
* src_span
;
470 LICE_pixel_chan
*pout
=dest
;
472 if (cury
< clipbottom
-1)
476 const unsigned int offs
=curx
>> 16;
477 const LICE_pixel_chan
*pin
= inptr
+ offs
*sizeof(LICE_pixel
);
478 if (offs
<clipright
-1)
481 __LICE_BilinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,curx
&0xffff,yfrac
);
482 DOPIX(pout
,r
,g
,b
,a
,ia
)
484 else if (offs
==clipright
-1)
487 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,yfrac
);
488 DOPIX(pout
,r
,g
,b
,a
,ia
)
491 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
495 else if (cury
== clipbottom
-1)
499 const unsigned int offs
=curx
>> 16;
500 const LICE_pixel_chan
*pin
= inptr
+ offs
*sizeof(LICE_pixel
);
501 if (offs
<clipright
-1)
504 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
),curx
&0xffff);
505 DOPIX(pout
,r
,g
,b
,a
,ia
)
507 else if (offs
==clipright
-1)
509 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],ia
)
512 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
524 const unsigned int cury
= icury
>> 16;
525 if (cury
< clipbottom
)
528 const LICE_pixel_chan
*inptr
=src
+ cury
* src_span
;
529 LICE_pixel_chan
*pout
=dest
;
533 const unsigned int offs
=curx
>> 16;
536 const LICE_pixel_chan
*pin
= inptr
+ offs
*sizeof(LICE_pixel
);
538 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],ia
)
541 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
555 #ifdef LICE_FAVOR_SPEED
556 template<class COMBFUNC
>
558 class _LICE_Template_Blit3
// stuff controlled by LICE_FAVOR_SPEED
560 #ifndef LICE_FAVOR_SPEED
561 #define DOPIX(pout,r,g,b,a,ia) combFunc(pout,r,g,b,a,ia);
563 #define DOPIX(pout,r,g,b,a,ia) COMBFUNC::doPix(pout,r,g,b,a,ia);
568 static void deltaBlit(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
,
569 int isrcx
, int isrcy
, int idsdx
, int idtdx
, int idsdy
, int idtdy
,
570 int idsdxdy
, int idtdxdy
,
571 unsigned int src_right
, unsigned int src_bottom
,
572 int src_span
, int dest_span
, int ia
, int filtermode
573 #ifndef LICE_FAVOR_SPEED
574 , LICE_COMBINEFUNC combFunc
578 if (filtermode
== LICE_BLIT_FILTER_BILINEAR
)
584 LICE_pixel_chan
*pout
=dest
;
588 const unsigned int cury
= thisy
>> 16;
589 const unsigned int curx
= thisx
>> 16;
590 if (cury
< src_bottom
-1)
592 if (curx
< src_right
-1)
594 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
597 __LICE_BilinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,thisx
&65535,thisy
&65535);
599 DOPIX(pout
,r
,g
,b
,a
,ia
);
601 else if (curx
==src_right
-1)
604 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
607 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,thisy
&65535);
608 DOPIX(pout
,r
,g
,b
,a
,ia
);
611 else if (cury
==src_bottom
-1)
613 if (curx
<src_right
-1)
615 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
619 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
),thisx
&65535);
621 DOPIX(pout
,r
,g
,b
,a
,ia
);
623 else if (curx
==src_right
-1)
625 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
626 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],ia
);
630 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
647 LICE_pixel_chan
*pout
=dest
;
651 const unsigned int cury
= thisy
>> 16;
652 const unsigned int curx
= thisx
>> 16;
653 if (cury
< src_bottom
&& curx
< src_right
)
655 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
657 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],ia
);
660 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
676 #ifdef LICE_FAVOR_SPEED
677 template<class COMBFUNC
>
679 class _LICE_Template_Blit4
// stuff controlled by LICE_FAVOR_SPEED
681 #ifndef LICE_FAVOR_SPEED
682 #define DOPIX(pout,r,g,b,a,ia) combFunc(pout,r,g,b,a,ia);
684 #define DOPIX(pout,r,g,b,a,ia) COMBFUNC::doPix(pout,r,g,b,a,ia);
689 static void deltaBlitAlpha(LICE_pixel_chan
*dest
, const LICE_pixel_chan
*src
, int w
, int h
,
690 int isrcx
, int isrcy
, int idsdx
, int idtdx
, int idsdy
, int idtdy
,
691 int idsdxdy
, int idtdxdy
,
692 unsigned int src_right
, unsigned int src_bottom
,
693 int src_span
, int dest_span
, int ia
, int idadx
, int idady
, int idadxdy
, int filtermode
694 #ifndef LICE_FAVOR_SPEED
695 , LICE_COMBINEFUNC combFunc
699 if (filtermode
== LICE_BLIT_FILTER_BILINEAR
)
706 LICE_pixel_chan
*pout
=dest
;
710 const unsigned int cury
= thisy
>> 16;
711 const unsigned int curx
= thisx
>> 16;
712 if (cury
< src_bottom
-1)
714 if (curx
< src_right
-1)
716 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
719 __LICE_BilinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,thisx
&65535,thisy
&65535);
721 DOPIX(pout
,r
,g
,b
,a
,thisa
>>8);
723 else if (curx
==src_right
-1)
726 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
729 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+src_span
,thisy
&65535);
730 DOPIX(pout
,r
,g
,b
,a
,thisa
>>8);
733 else if (cury
==src_bottom
-1)
735 if (curx
<src_right
-1)
737 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
741 __LICE_LinearFilterI(&r
,&g
,&b
,&a
,pin
,pin
+sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
),thisx
&65535);
743 DOPIX(pout
,r
,g
,b
,a
,thisa
>>8);
745 else if (curx
==src_right
-1)
747 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
748 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],thisa
>>8);
752 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
773 LICE_pixel_chan
*pout
=dest
;
777 const unsigned int cury
= thisy
>> 16;
778 const unsigned int curx
= thisx
>> 16;
779 if (cury
< src_bottom
&& curx
< src_right
)
781 const LICE_pixel_chan
*pin
= src
+ cury
* src_span
+ curx
*sizeof(LICE_pixel
);
783 DOPIX(pout
,pin
[LICE_PIXEL_R
],pin
[LICE_PIXEL_G
],pin
[LICE_PIXEL_B
],pin
[LICE_PIXEL_A
],thisa
>>8);
786 pout
+= sizeof(LICE_pixel
)/sizeof(LICE_pixel_chan
);
807 #ifndef LICE_NO_GRADIENT_SUPPORT
809 void LICE_GradRect(LICE_IBitmap
*dest
, int dstx
, int dsty
, int dstw
, int dsth
,
810 float ir
, float ig
, float ib
, float ia
,
811 float drdx
, float dgdx
, float dbdx
, float dadx
,
812 float drdy
, float dgdy
, float dbdy
, float dady
,
817 ir
*=255.0; ig
*=255.0; ib
*=255.0; ia
*=256.0;
818 drdx
*=255.0; dgdx
*=255.0; dbdx
*=255.0; dadx
*=256.0;
819 drdy
*=255.0; dgdy
*=255.0; dbdy
*=255.0; dady
*=256.0;
825 ir
-=dstx
*drdx
; ig
-=dstx
*dgdx
; ib
-=dstx
*dbdx
; ia
-=dstx
*dadx
;
831 ir
-= dsty
*drdy
; ig
-=dsty
*dgdy
; ib
-= dsty
*dbdy
; ia
-= dsty
*dady
;
836 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
837 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
839 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
841 if (!pdest
|| !dest_span
|| dstw
< 1 || dsth
< 1 || dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
843 if (dstw
> destbm_w
-dstx
) dstw
= destbm_w
-dstx
;
844 if (dsth
> destbm_h
-dsty
) dsth
= destbm_h
-dsty
;
846 if (dest
->isFlipped())
848 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
849 dest_span
=-dest_span
;
853 pdest
+= dsty
*dest_span
;
855 pdest
+=dstx
*sizeof(LICE_pixel
);
856 #define TOFIX(a) ((int)((a)*65536.0))
858 int iir
=TOFIX(ir
), iig
=TOFIX(ig
), iib
=TOFIX(ib
), iia
=TOFIX(ia
), idrdx
=TOFIX(drdx
),idgdx
=TOFIX(dgdx
),idbdx
=TOFIX(dbdx
),idadx
=TOFIX(dadx
),
859 idrdy
=TOFIX(drdy
), idgdy
=TOFIX(dgdy
), idbdy
=TOFIX(dbdy
), idady
=TOFIX(dady
);
862 #ifdef LICE_FAVOR_SIZE_EXTREME
863 LICE_COMBINEFUNC blitfunc
=NULL
;
864 #define __LICE__ACTION(comb) blitfunc=comb::doPix;
867 #define __LICE__ACTION(comb) _LICE_Template_Blit1<comb>::gradBlit(pdest,dstw,dsth,iir,iig,iib,iia,idrdx,idgdx,idbdx,idadx,idrdy,idgdy,idbdy,idady,dest_span)
870 // todo: could predict whether or not the colors will ever go out of 0.255 range and optimize
872 if ((mode
& LICE_BLIT_MODE_MASK
)==LICE_BLIT_MODE_COPY
&& iia
==65536 && idady
==0 && idadx
== 0)
874 __LICE__ACTION(_LICE_CombinePixelsClobberClamp
);
878 __LICE_ACTION_NOSRCALPHA(mode
,256,true);
880 #undef __LICE__ACTION
882 #ifdef LICE_FAVOR_SIZE_EXTREME
883 if (blitfunc
) _LICE_Template_Blit1::gradBlit(pdest
,dstw
,dsth
,iir
,iig
,iib
,iia
,idrdx
,idgdx
,idbdx
,idadx
,idrdy
,idgdy
,idbdy
,idady
,dest_span
,blitfunc
);
892 #ifndef LICE_NO_BLIT_SUPPORT
893 void LICE_Blit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
, int dstx
, int dsty
, int srcx
, int srcy
, int srcw
, int srch
, float alpha
, int mode
)
895 RECT r
={srcx
,srcy
,srcx
+srcw
,srcy
+srch
};
896 LICE_Blit(dest
,src
,dstx
,dsty
,&r
,alpha
,mode
);
899 void LICE_Blit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
, int dstx
, int dsty
, const RECT
*srcrect
, float alpha
, int mode
)
901 if (!dest
|| !src
|| !alpha
) return;
903 RECT sr
={0,0,src
->getWidth(),src
->getHeight()};
907 if (sr
.left
< 0) { dstx
-=sr
.left
; sr
.left
=0; }
908 if (sr
.top
< 0) { dsty
-=sr
.top
; sr
.top
=0; }
909 if (sr
.right
> src
->getWidth()) sr
.right
=src
->getWidth();
910 if (sr
.bottom
> src
->getHeight()) sr
.bottom
= src
->getHeight();
914 if (dstx
< 0) { sr
.left
-= dstx
; dstx
=0; }
915 if (dsty
< 0) { sr
.top
-= dsty
; dsty
=0; }
917 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
918 if (sr
.right
<= sr
.left
|| sr
.bottom
<= sr
.top
|| dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
920 if (sr
.right
> sr
.left
+ (destbm_w
-dstx
)) sr
.right
= sr
.left
+ (destbm_w
-dstx
);
921 if (sr
.bottom
> sr
.top
+ (destbm_h
-dsty
)) sr
.bottom
= sr
.top
+ (destbm_h
-dsty
);
923 // ignore blits that are 0
924 if (sr
.right
<= sr
.left
|| sr
.bottom
<= sr
.top
) return;
926 #ifndef DISABLE_LICE_EXTENSIONS
927 if (dest
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_BLIT_ACCEL
))
929 LICE_Ext_Blit_acceldata
data(src
, dstx
, dsty
,
931 sr
.right
-sr
.left
, sr
.bottom
-sr
.top
,
933 if (dest
->Extended(LICE_EXT_BLIT_ACCEL
, &data
)) return;
938 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
939 int src_span
=src
->getRowSpan()*sizeof(LICE_pixel
);
940 const LICE_pixel_chan
*psrc
= (LICE_pixel_chan
*)src
->getBits();
941 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
942 if (!psrc
|| !pdest
) return;
944 if (src
->isFlipped())
946 psrc
+= (src
->getHeight()-sr
.top
- 1)*src_span
;
949 else psrc
+= sr
.top
*src_span
;
950 psrc
+= sr
.left
*sizeof(LICE_pixel
);
952 if (dest
->isFlipped())
954 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
955 dest_span
=-dest_span
;
957 else pdest
+= dsty
*dest_span
;
958 pdest
+=dstx
*sizeof(LICE_pixel
);
960 int i
=sr
.bottom
-sr
.top
;
961 int cpsize
=sr
.right
-sr
.left
;
963 if ((mode
&LICE_BLIT_MODE_MASK
) >= LICE_BLIT_MODE_CHANCOPY
&& (mode
&LICE_BLIT_MODE_MASK
) < LICE_BLIT_MODE_CHANCOPY
+0x10)
967 LICE_pixel_chan
*o
=pdest
+((mode
>>2)&3);
968 const LICE_pixel_chan
*in
=psrc
+(mode
&3);
973 o
+=sizeof(LICE_pixel
);
974 in
+=sizeof(LICE_pixel
);
980 // special fast case for copy with no source alpha and alpha=1.0 or 0.5
981 else if ((mode
&(LICE_BLIT_MODE_MASK
|LICE_BLIT_USE_ALPHA
))==LICE_BLIT_MODE_COPY
&& (alpha
==1.0||alpha
==0.5))
988 const LICE_pixel
*rd
= (LICE_pixel
*)psrc
;
989 LICE_pixel
*wr
= (LICE_pixel
*)pdest
;
992 *wr
= ((*wr
>>1)&0x7f7f7f7f)+((*rd
++>>1)&0x7f7f7f7f);
1004 memcpy(pdest
,psrc
,cpsize
*sizeof(LICE_pixel
));
1012 int ia
=(int)(alpha
*256.0);
1013 #ifdef LICE_FAVOR_SIZE
1014 LICE_COMBINEFUNC blitfunc
=NULL
;
1015 #define __LICE__ACTION(comb) blitfunc=comb::doPix;
1017 #define __LICE__ACTION(comb) _LICE_Template_Blit2<comb>::blit(pdest,psrc,cpsize,i,src_span,dest_span,ia)
1020 __LICE_ACTION_SRCALPHA(mode
,ia
,false);
1022 #undef __LICE__ACTION
1024 #ifdef LICE_FAVOR_SIZE
1025 if (blitfunc
) _LICE_Template_Blit2::blit(pdest
,psrc
,cpsize
,i
,src_span
,dest_span
,ia
,blitfunc
);
1032 #ifndef LICE_NO_BLUR_SUPPORT
1034 void LICE_Blur(LICE_IBitmap
*dest
, LICE_IBitmap
*src
, int dstx
, int dsty
, int srcx
, int srcy
, int srcw
, int srch
) // src and dest can overlap, however it may look fudgy if they do
1036 if (!dest
|| !src
) return;
1038 RECT sr
={srcx
,srcy
,srcx
+srcw
,srcy
+srch
};
1039 if (sr
.left
< 0) sr
.left
=0;
1040 if (sr
.top
< 0) sr
.top
=0;
1041 if (sr
.right
> src
->getWidth()) sr
.right
=src
->getWidth();
1042 if (sr
.bottom
> src
->getHeight()) sr
.bottom
= src
->getHeight();
1045 if (dstx
< 0) { sr
.left
-= dstx
; dstx
=0; }
1046 if (dsty
< 0) { sr
.top
-= dsty
; dsty
=0; }
1048 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1049 if (sr
.right
<= sr
.left
|| sr
.bottom
<= sr
.top
|| dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
1051 if (sr
.right
> sr
.left
+ (destbm_w
-dstx
)) sr
.right
= sr
.left
+ (destbm_w
-dstx
);
1052 if (sr
.bottom
> sr
.top
+ (destbm_h
-dsty
)) sr
.bottom
= sr
.top
+ (destbm_h
-dsty
);
1054 // ignore blits that are smaller than 2x2
1055 if (sr
.right
<= sr
.left
+1 || sr
.bottom
<= sr
.top
+1) return;
1057 int dest_span
=dest
->getRowSpan();
1058 int src_span
=src
->getRowSpan();
1059 const LICE_pixel
*psrc
= (LICE_pixel
*)src
->getBits();
1060 LICE_pixel
*pdest
= (LICE_pixel
*)dest
->getBits();
1061 if (!psrc
|| !pdest
) return;
1063 if (src
->isFlipped())
1065 psrc
+= (src
->getHeight()-sr
.top
- 1)*src_span
;
1068 else psrc
+= sr
.top
*src_span
;
1071 if (dest
->isFlipped())
1073 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
1074 dest_span
=-dest_span
;
1076 else pdest
+= dsty
*dest_span
;
1079 LICE_pixel
*tmpbuf
=NULL
;
1080 int w
=sr
.right
-sr
.left
;
1082 // buffer to save the last unprocessed lines for the cases where blurring from a bitmap to itself
1083 LICE_pixel turdbuf
[2048];
1086 if (w
<= (int) (sizeof(turdbuf
)/sizeof(turdbuf
[0])/2)) tmpbuf
=turdbuf
;
1087 else tmpbuf
=(LICE_pixel
*)malloc(w
*2*sizeof(LICE_pixel
));
1091 for (i
= sr
.top
; i
< sr
.bottom
; i
++)
1094 memcpy(tmpbuf
+((i
&1)?w
:0),psrc
,w
*sizeof(LICE_pixel
));
1096 if (i
==sr
.top
|| i
==sr
.bottom
-1)
1098 const LICE_pixel
*psrc2
=psrc
+(i
==sr
.top
? src_span
: -src_span
);
1102 pdest
[0] = LICE_PIXEL_HALF(lp
=psrc
[0]) +
1103 LICE_PIXEL_QUARTER(psrc
[1]) +
1104 LICE_PIXEL_QUARTER(psrc2
[0]);
1106 for (x
= 1; x
< w
-1; x
++)
1109 pdest
[x
] = LICE_PIXEL_HALF(tp
=psrc
[x
]) +
1110 LICE_PIXEL_QUARTER(psrc2
[x
]) +
1111 LICE_PIXEL_EIGHTH(psrc
[x
+1]) +
1112 LICE_PIXEL_EIGHTH(lp
);
1115 pdest
[x
] = LICE_PIXEL_HALF(psrc
[x
]) +
1116 LICE_PIXEL_QUARTER(lp
) +
1117 LICE_PIXEL_QUARTER(psrc2
[x
]);
1121 const LICE_pixel
*psrc2
=psrc
-src_span
;
1122 const LICE_pixel
*psrc3
=psrc
+src_span
;
1124 psrc2
=tmpbuf
+ ((i
&1) ? 0 : w
);
1127 pdest
[0] = LICE_PIXEL_HALF(lp
=psrc
[0]) +
1128 LICE_PIXEL_QUARTER(psrc
[1]) +
1129 LICE_PIXEL_EIGHTH(psrc2
[0]) +
1130 LICE_PIXEL_EIGHTH(psrc3
[0]);
1132 for (x
= 1; x
< w
-1; x
++)
1135 pdest
[x
] = LICE_PIXEL_HALF(tp
=psrc
[x
]) +
1136 LICE_PIXEL_EIGHTH(psrc
[x
+1]) +
1137 LICE_PIXEL_EIGHTH(lp
) +
1138 LICE_PIXEL_EIGHTH(psrc2
[x
]) +
1139 LICE_PIXEL_EIGHTH(psrc3
[x
]);
1142 pdest
[x
] = LICE_PIXEL_HALF(psrc
[x
]) +
1143 LICE_PIXEL_QUARTER(lp
) +
1144 LICE_PIXEL_EIGHTH(psrc2
[x
]) +
1145 LICE_PIXEL_EIGHTH(psrc3
[x
]);
1150 if (tmpbuf
&& tmpbuf
!= turdbuf
)
1156 #ifndef LICE_NO_BLIT_SUPPORT
1157 void LICE_ScaledBlit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
1158 int dstx
, int dsty
, int dstw
, int dsth
,
1159 float srcx
, float srcy
, float srcw
, float srch
,
1160 float alpha
, int mode
)
1162 if (!dest
|| !src
|| !dstw
|| !dsth
|| !alpha
) return;
1164 // non-scaling optimized omde
1165 if (fabs(srcw
-dstw
)<0.001 && fabs(srch
-dsth
)<0.001)
1167 // and if not bilinear filtering, or
1168 // the source coordinates are near their integer counterparts
1169 if ((mode
&LICE_BLIT_FILTER_MASK
)!=LICE_BLIT_FILTER_BILINEAR
||
1170 (fabs(srcx
-floor(srcx
+0.5f
))<0.03 && fabs(srcy
-floor(srcy
+0.5f
))<0.03))
1172 RECT sr
={(int)(srcx
+0.5f
),(int)(srcy
+0.5f
),};
1173 sr
.right
=sr
.left
+dstw
;
1174 sr
.bottom
=sr
.top
+dsth
;
1175 LICE_Blit(dest
,src
,dstx
,dsty
,&sr
,alpha
,mode
);
1180 #ifndef DISABLE_LICE_EXTENSIONS
1181 if (dest
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_SCALEDBLIT_ACCEL
))
1183 LICE_Ext_ScaledBlit_acceldata
data(src
, dstx
, dsty
, dstw
, dsth
, srcx
, srcy
, srcw
, srch
, alpha
, mode
);
1184 if (dest
->Extended(LICE_EXT_SCALEDBLIT_ACCEL
, &data
)) return;
1203 double xadvance
= srcw
/ dstw
;
1204 double yadvance
= srch
/ dsth
;
1206 if (dstx
< 0) { srcx
-= (float) (dstx
*xadvance
); dstw
+=dstx
; dstx
=0; }
1207 if (dsty
< 0) { srcy
-= (float) (dsty
*yadvance
); dsth
+=dsty
; dsty
=0; }
1209 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1210 if (dstw
< 1 || dsth
< 1 || dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
1212 if (dstw
> destbm_w
-dstx
) dstw
=destbm_w
-dstx
;
1213 if (dsth
> destbm_h
-dsty
) dsth
=destbm_h
-dsty
;
1215 int idx
=(int)(xadvance
*65536.0);
1216 int idy
=(int)(yadvance
*65536.0);
1217 int icurx
=(int) (srcx
*65536.0);
1218 int icury
=(int) (srcy
*65536.0);
1222 // the clip area calculations need to be done fixed point so the results match runtime
1226 if (icurx
< 0) // increase dstx, decrease dstw
1228 int n
= (idx
-1-icurx
)/idx
;
1233 if ((icurx
+ idx
*(dstw
-1))/65536 >= src
->getWidth())
1235 int neww
= ((src
->getWidth()-1)*65536 - icurx
)/idx
;
1236 if (neww
< dstw
) dstw
=neww
;
1241 // todo: optimize source-clipping with reversed X axis
1246 if (icury
< 0) // increase dsty, decrease dsth
1248 int n
= (idy
-1-icury
)/idy
;
1253 if ((icury
+ idy
*(dsth
-1))/65536 >= src
->getHeight())
1255 int newh
= ((src
->getHeight()-1)*65536 - icury
)/idy
;
1256 if (newh
< dsth
) dsth
=newh
;
1261 // todo: optimize source-clipping with reversed Y axis (check icury against src->getHeight(), etc)
1263 if (dstw
<1 || dsth
<1) return;
1267 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
1268 int src_span
=src
->getRowSpan()*sizeof(LICE_pixel
);
1270 const LICE_pixel_chan
*psrc
= (const LICE_pixel_chan
*)src
->getBits();
1271 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
1272 if (!psrc
|| !pdest
) return;
1275 if (src
->isFlipped())
1277 psrc
+= (src
->getHeight()-1)*src_span
;
1281 if (dest
->isFlipped())
1283 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
1284 dest_span
=-dest_span
;
1286 else pdest
+= dsty
*dest_span
;
1287 pdest
+=dstx
*sizeof(LICE_pixel
);
1289 int clip_r
=(int)(srcx
+lice_max(srcw
,0)+0.999999);
1290 int clip_b
=(int)(srcy
+lice_max(srch
,0)+0.999999);
1291 if (clip_r
>src
->getWidth()) clip_r
=src
->getWidth();
1292 if (clip_b
>src
->getHeight()) clip_b
=src
->getHeight();
1294 if (clip_r
<1||clip_b
<1) return;
1296 int ia
=(int)(alpha
*256.0);
1298 if ((mode
&(LICE_BLIT_FILTER_MASK
|LICE_BLIT_MODE_MASK
|LICE_BLIT_USE_ALPHA
))==LICE_BLIT_MODE_COPY
&& (ia
==128 || ia
==256))
1302 _LICE_Template_Blit0
<_LICE_CombinePixelsHalfMixFAST
>::scaleBlitFAST(pdest
,psrc
,dstw
,dsth
,icurx
,icury
,idx
,idy
,clip_r
,clip_b
,src_span
,dest_span
);
1306 _LICE_Template_Blit0
<_LICE_CombinePixelsClobberFAST
>::scaleBlitFAST(pdest
,psrc
,dstw
,dsth
,icurx
,icury
,idx
,idy
,clip_r
,clip_b
,src_span
,dest_span
);
1311 if (xadvance
>=1.7 && yadvance
>=1.7 && (mode
&LICE_BLIT_FILTER_MASK
)==LICE_BLIT_FILTER_BILINEAR
)
1313 int msc
= lice_max(idx
,idy
);
1314 const int filtsz
=msc
>(3<<16) ? 5 : 3;
1315 const int filt_start
= - (filtsz
/2);
1317 int filter
[25]; // 5x5 max
1321 // sprintf(buf,"filter, msc=%f: ",msc);
1323 for(y
=0;y
<filtsz
;y
++)
1326 for(x
=0;x
<filtsz
;x
++)
1328 if (x
==y
&& x
==filtsz
/2) *p
++ = 65536; // src pix is always valued at 1.
1331 double dx
=x
+filt_start
;
1332 double dy
=y
+filt_start
;
1333 double v
= (msc
-1.0) / sqrt(dx
*dx
+dy
*dy
); // this needs serious tweaking...
1335 // sprintf(buf+strlen(buf),"%f,",v);
1338 else if (v
>1.0) *p
++=65536;
1339 else *p
++=(int)(v
*65536.0);
1343 // OutputDebugString(buf);
1346 #ifdef LICE_FAVOR_SIZE
1347 LICE_COMBINEFUNC blitfunc
=NULL
;
1348 #define __LICE__ACTION(comb) blitfunc=comb::doPix;
1350 #define __LICE__ACTION(comb) _LICE_Template_Blit2<comb>::scaleBlitFilterDown(pdest,psrc,dstw,dsth,icurx,icury,idx,idy,clip_r,clip_b,src_span,dest_span,ia,filter,filt_start,filtsz)
1352 __LICE_ACTION_SRCALPHA(mode
,ia
,false);
1353 #undef __LICE__ACTION
1355 #ifdef LICE_FAVOR_SIZE
1356 if (blitfunc
) _LICE_Template_Blit2::scaleBlitFilterDown(pdest
,psrc
,dstw
,dsth
,icurx
,icury
,idx
,idy
,clip_r
,clip_b
,src_span
,dest_span
,ia
,filter
,filt_start
,filtsz
,blitfunc
);
1362 #ifdef LICE_FAVOR_SIZE
1363 LICE_COMBINEFUNC blitfunc
=NULL
;
1364 #define __LICE__ACTION(comb) blitfunc=comb::doPix;
1366 #define __LICE__ACTION(comb) _LICE_Template_Blit2<comb>::scaleBlit(pdest,psrc,dstw,dsth,icurx,icury,idx,idy,clip_r,clip_b,src_span,dest_span,ia,mode&LICE_BLIT_FILTER_MASK)
1368 __LICE_ACTION_SRCALPHA(mode
,ia
,false);
1369 #undef __LICE__ACTION
1370 #ifdef LICE_FAVOR_SIZE
1371 if (blitfunc
) _LICE_Template_Blit2::scaleBlit(pdest
,psrc
,dstw
,dsth
,icurx
,icury
,idx
,idy
,clip_r
,clip_b
,src_span
,dest_span
,ia
,mode
&LICE_BLIT_FILTER_MASK
,blitfunc
);
1377 void LICE_DeltaBlit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
1378 int dstx
, int dsty
, int dstw
, int dsth
,
1379 float srcx
, float srcy
, float srcw
, float srch
,
1380 double dsdx
, double dtdx
, double dsdy
, double dtdy
,
1381 double dsdxdy
, double dtdxdy
,
1382 bool cliptosourcerect
, float alpha
, int mode
)
1384 if (!dest
|| !src
|| !dstw
|| !dsth
) return;
1386 double src_top
=0.0,src_left
=0.0,src_right
=src
->getWidth(),src_bottom
=src
->getHeight();
1388 if (cliptosourcerect
)
1390 if (srcx
> src_left
) src_left
=srcx
;
1391 if (srcy
> src_top
) src_top
=srcy
;
1392 if (srcx
+srcw
< src_right
) src_right
=srcx
+srcw
;
1393 if (srcy
+srch
< src_bottom
) src_bottom
=srcy
+srch
;
1412 srcx
-= (float) (dstx
*dsdx
);
1413 srcy
-= (float) (dstx
*dtdx
);
1419 srcy
-= (float) (dsty
*dtdy
);
1420 srcx
-= (float) (dsty
*dsdy
);
1425 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1426 if (dstw
< 1 || dsth
< 1 || dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
1428 if (dstw
> destbm_w
-dstx
) dstw
=destbm_w
-dstx
;
1429 if (dsth
> destbm_h
-dsty
) dsth
=destbm_h
-dsty
;
1432 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
1433 int src_span
=src
->getRowSpan()*sizeof(LICE_pixel
);
1435 const LICE_pixel_chan
*psrc
= (LICE_pixel_chan
*)src
->getBits();
1436 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
1437 if (!psrc
|| !pdest
) return;
1439 if (src
->isFlipped())
1441 psrc
+= (src
->getHeight()-1)*src_span
;
1445 if (dest
->isFlipped())
1447 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
1448 dest_span
=-dest_span
;
1450 else pdest
+= dsty
*dest_span
;
1451 pdest
+=dstx
*sizeof(LICE_pixel
);
1453 int sl
=(int)(src_left
);
1454 int sr
=(int)(src_right
);
1455 int st
=(int)(src_top
);
1456 int sb
=(int)(src_bottom
);
1460 if (sr
< 1 || sb
< 1) return;
1462 psrc
+= src_span
* st
+ sl
* sizeof(LICE_pixel
);
1464 int ia
=(int)(alpha
*256.0);
1465 int isrcx
=(int)(srcx
*65536.0);
1466 int isrcy
=(int)(srcy
*65536.0);
1467 int idsdx
=(int)(dsdx
*65536.0);
1468 int idtdx
=(int)(dtdx
*65536.0);
1469 int idsdy
=(int)(dsdy
*65536.0);
1470 int idtdy
=(int)(dtdy
*65536.0);
1471 int idsdxdy
=(int)(dsdxdy
*65536.0);
1472 int idtdxdy
=(int)(dtdxdy
*65536.0);
1474 #ifndef LICE_FAVOR_SPEED
1475 LICE_COMBINEFUNC blitfunc
=NULL
;
1476 #define __LICE__ACTION(comb) blitfunc = comb::doPix;
1478 #define __LICE__ACTION(comb) _LICE_Template_Blit3<comb>::deltaBlit(pdest,psrc,dstw,dsth,isrcx,isrcy,idsdx,idtdx,idsdy,idtdy,idsdxdy,idtdxdy,sr,sb,src_span,dest_span,ia,mode&LICE_BLIT_FILTER_MASK)
1480 __LICE_ACTION_SRCALPHA(mode
,ia
,false);
1481 #undef __LICE__ACTION
1483 #ifndef LICE_FAVOR_SPEED
1484 if (blitfunc
) _LICE_Template_Blit3::deltaBlit(pdest
,psrc
,dstw
,dsth
,isrcx
,isrcy
,idsdx
,idtdx
,idsdy
,idtdy
,idsdxdy
,idtdxdy
,sr
,sb
,src_span
,dest_span
,ia
,mode
&LICE_BLIT_FILTER_MASK
,blitfunc
);
1489 void LICE_DeltaBlitAlpha(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
1490 int dstx
, int dsty
, int dstw
, int dsth
,
1491 float srcx
, float srcy
, float srcw
, float srch
,
1492 double dsdx
, double dtdx
, double dsdy
, double dtdy
,
1493 double dsdxdy
, double dtdxdy
,
1494 bool cliptosourcerect
, float alpha
, int mode
, double dadx
, double dady
, double dadxdy
)
1496 if (!dest
|| !src
|| !dstw
|| !dsth
) return;
1498 const double eps
= 0.0001;
1499 if (fabs(dadx
*dstw
) < eps
&& fabs(dady
*dsth
) < eps
&& fabs(dadxdy
*dsth
) < eps
)
1501 LICE_DeltaBlit(dest
, src
, dstx
, dsty
, dstw
, dsth
, srcx
, srcy
, srcw
, srch
, dsdx
, dtdx
, dsdy
, dtdy
, dsdxdy
, dtdxdy
, cliptosourcerect
, alpha
, mode
);
1505 double src_top
=0.0,src_left
=0.0,src_right
=src
->getWidth(),src_bottom
=src
->getHeight();
1507 if (cliptosourcerect
)
1509 if (srcx
> src_left
) src_left
=srcx
;
1510 if (srcy
> src_top
) src_top
=srcy
;
1511 if (srcx
+srcw
< src_right
) src_right
=srcx
+srcw
;
1512 if (srcy
+srch
< src_bottom
) src_bottom
=srcy
+srch
;
1531 alpha
-= (float) (dstx
*dadx
);
1532 srcx
-= (float) (dstx
*dsdx
);
1533 srcy
-= (float) (dstx
*dtdx
);
1539 alpha
-= (float) (dsty
*dady
);
1540 srcy
-= (float) (dsty
*dtdy
);
1541 srcx
-= (float) (dsty
*dsdy
);
1546 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1547 if (dstw
< 1 || dsth
< 1 || dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
1549 if (dstw
> destbm_w
-dstx
) dstw
=destbm_w
-dstx
;
1550 if (dsth
> destbm_h
-dsty
) dsth
=destbm_h
-dsty
;
1553 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
1554 int src_span
=src
->getRowSpan()*sizeof(LICE_pixel
);
1556 const LICE_pixel_chan
*psrc
= (LICE_pixel_chan
*)src
->getBits();
1557 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
1558 if (!psrc
|| !pdest
) return;
1560 if (src
->isFlipped())
1562 psrc
+= (src
->getHeight()-1)*src_span
;
1566 if (dest
->isFlipped())
1568 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
1569 dest_span
=-dest_span
;
1571 else pdest
+= dsty
*dest_span
;
1572 pdest
+=dstx
*sizeof(LICE_pixel
);
1574 int sl
=(int)(src_left
);
1575 int sr
=(int)(src_right
);
1576 int st
=(int)(src_top
);
1577 int sb
=(int)(src_bottom
);
1581 if (sr
< 1 || sb
< 1) return;
1583 psrc
+= src_span
* st
+ sl
* sizeof(LICE_pixel
);
1585 int ia
=(int)(alpha
*65536.0);
1586 int isrcx
=(int)(srcx
*65536.0);
1587 int isrcy
=(int)(srcy
*65536.0);
1588 int idsdx
=(int)(dsdx
*65536.0);
1589 int idtdx
=(int)(dtdx
*65536.0);
1590 int idsdy
=(int)(dsdy
*65536.0);
1591 int idtdy
=(int)(dtdy
*65536.0);
1592 int idsdxdy
=(int)(dsdxdy
*65536.0);
1593 int idtdxdy
=(int)(dtdxdy
*65536.0);
1595 int idadx
=(int)(dadx
*65536.0);
1596 int idady
=(int)(dady
*65536.0);
1597 int idadxdy
=(int)(dadxdy
*65536.0);
1599 #ifndef LICE_FAVOR_SPEED
1600 LICE_COMBINEFUNC blitfunc
=NULL
;
1601 #define __LICE__ACTION(comb) blitfunc = comb::doPix;
1603 #define __LICE__ACTION(comb) _LICE_Template_Blit4<comb>::deltaBlitAlpha(pdest,psrc,dstw,dsth,isrcx,isrcy,idsdx,idtdx,idsdy,idtdy,idsdxdy,idtdxdy,sr,sb,src_span,dest_span,ia,idadx,idady,idadxdy,mode&LICE_BLIT_FILTER_MASK)
1605 __LICE_ACTION_NOSRCALPHA(mode
,256,true);
1606 #undef __LICE__ACTION
1608 #ifndef LICE_FAVOR_SPEED
1609 if (blitfunc
) _LICE_Template_Blit4::deltaBlitAlpha(pdest
,psrc
,dstw
,dsth
,isrcx
,isrcy
,idsdx
,idtdx
,idsdy
,idtdy
,idsdxdy
,idtdxdy
,sr
,sb
,src_span
,dest_span
,ia
,idadx
,idady
,idadxdy
,mode
&LICE_BLIT_FILTER_MASK
,blitfunc
);
1617 void LICE_RotatedBlit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
1618 int dstx
, int dsty
, int dstw
, int dsth
,
1619 float srcx
, float srcy
, float srcw
, float srch
,
1621 bool cliptosourcerect
, float alpha
, int mode
, float rotxcent
, float rotycent
)
1623 if (!dest
|| !src
|| !dstw
|| !dsth
) return;
1625 double src_top
=0.0,src_left
=0.0,src_right
=src
->getWidth(),src_bottom
=src
->getHeight();
1627 if (cliptosourcerect
)
1629 if (srcx
> src_left
) src_left
=srcx
;
1630 if (srcy
> src_top
) src_top
=srcy
;
1631 if (srcx
+srcw
< src_right
) src_right
=srcx
+srcw
;
1632 if (srcy
+srch
< src_bottom
) src_bottom
=srcy
+srch
;
1650 double cosa
=cos(angle
);
1651 double sina
=sin(angle
);
1653 double xsc
=srcw
/ dstw
;
1654 double ysc
=srch
/ dsth
;
1656 double dsdx
= xsc
* cosa
;
1657 double dtdy
= ysc
* cosa
;
1658 double dsdy
= xsc
* sina
;
1659 double dtdx
= ysc
* -sina
;
1661 srcx
-= (float) (0.5 * (dstw
*dsdx
+ dsth
*dsdy
- srcw
) - rotxcent
);
1662 srcy
-= (float) (0.5 * (dsth
*dtdy
+ dstw
*dtdx
- srch
) - rotycent
);
1666 srcx
-= (float) (dstx
*dsdx
);
1667 srcy
-= (float) (dstx
*dtdx
);
1673 srcy
-= (float) (dsty
*dtdy
);
1674 srcx
-= (float) (dsty
*dsdy
);
1679 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1680 if (dstw
< 1 || dsth
< 1 || dstx
>= destbm_w
|| dsty
>= destbm_h
) return;
1682 if (dstw
> destbm_w
-dstx
) dstw
=destbm_w
-dstx
;
1683 if (dsth
> destbm_h
-dsty
) dsth
=destbm_h
-dsty
;
1686 int dest_span
=dest
->getRowSpan()*sizeof(LICE_pixel
);
1687 int src_span
=src
->getRowSpan()*sizeof(LICE_pixel
);
1689 const LICE_pixel_chan
*psrc
= (LICE_pixel_chan
*)src
->getBits();
1690 LICE_pixel_chan
*pdest
= (LICE_pixel_chan
*)dest
->getBits();
1691 if (!psrc
|| !pdest
) return;
1693 if (src
->isFlipped())
1695 psrc
+= (src
->getHeight()-1)*src_span
;
1699 if (dest
->isFlipped())
1701 pdest
+= (destbm_h
-dsty
- 1)*dest_span
;
1702 dest_span
=-dest_span
;
1704 else pdest
+= dsty
*dest_span
;
1705 pdest
+=dstx
*sizeof(LICE_pixel
);
1707 int sl
=(int)(src_left
);
1708 int sr
=(int)(src_right
);
1709 int st
=(int)(src_top
);
1710 int sb
=(int)(src_bottom
);
1714 if (sr
< 1 || sb
< 1) return;
1716 psrc
+= src_span
* st
+ sl
* sizeof(LICE_pixel
);
1718 int ia
=(int)(alpha
*256.0);
1719 int isrcx
=(int)(srcx
*65536.0);
1720 int isrcy
=(int)(srcy
*65536.0);
1721 int idsdx
=(int)(dsdx
*65536.0);
1722 int idtdx
=(int)(dtdx
*65536.0);
1723 int idsdy
=(int)(dsdy
*65536.0);
1724 int idtdy
=(int)(dtdy
*65536.0);
1726 #ifndef LICE_FAVOR_SPEED
1727 LICE_COMBINEFUNC blitfunc
=NULL
;
1728 #define __LICE__ACTION(comb) blitfunc = comb::doPix;
1730 #define __LICE__ACTION(comb) _LICE_Template_Blit3<comb>::deltaBlit(pdest,psrc,dstw,dsth,isrcx,isrcy,idsdx,idtdx,idsdy,idtdy,0,0,sr,sb,src_span,dest_span,ia,mode&LICE_BLIT_FILTER_MASK)
1732 __LICE_ACTION_SRCALPHA(mode
,ia
,false);
1733 #undef __LICE__ACTION
1735 #ifndef LICE_FAVOR_SPEED
1736 if (blitfunc
) _LICE_Template_Blit3::deltaBlit(pdest
,psrc
,dstw
,dsth
,isrcx
,isrcy
,idsdx
,idtdx
,idsdy
,idtdy
,0,0,sr
,sb
,src_span
,dest_span
,ia
,mode
&LICE_BLIT_FILTER_MASK
,blitfunc
);
1743 void LICE_Clear(LICE_IBitmap
*dest
, LICE_pixel color
)
1747 #ifndef DISABLE_LICE_EXTENSIONS
1748 if (dest
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_CLEAR_ACCEL
))
1750 if (dest
->Extended(LICE_EXT_CLEAR_ACCEL
, &color
)) return;
1754 LICE_pixel
*p
=dest
->getBits();
1755 int h
=dest
->getHeight();
1756 const int w
=dest
->getWidth();
1757 const int sp
=dest
->getRowSpan();
1758 if (!p
|| w
<1 || h
<1 || !sp
) return;
1763 while (n
--) *p
++ = color
;
1771 void LICE_MultiplyAddRect(LICE_IBitmap
*dest
, int x
, int y
, int w
, int h
,
1772 float rsc
, float gsc
, float bsc
, float asc
,
1773 float radd
, float gadd
, float badd
, float aadd
)
1777 if (x
<0) { w
+=x
; x
=0; }
1778 if (y
<0) { h
+=y
; y
=0; }
1780 LICE_pixel
*p
=dest
->getBits();
1781 const int sp
=dest
->getRowSpan();
1782 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1783 if (!p
|| !sp
|| w
<1 || h
< 1 || x
>= destbm_w
|| y
>= destbm_h
) return;
1785 if (w
>destbm_w
-x
) w
=destbm_w
-x
;
1786 if (h
>destbm_h
-y
) h
=destbm_h
-y
;
1788 if (dest
->isFlipped())
1790 p
+=(destbm_h
- y
- h
)*sp
;
1799 int ir
=(int)(rsc
*256.0);
1800 int ig
=(int)(gsc
*256.0);
1801 int ib
=(int)(bsc
*256.0);
1802 int ia
=(int)(asc
*256.0);
1803 int ir2
=(int)(radd
*256.0);
1804 int ig2
=(int)(gadd
*256.0);
1805 int ib2
=(int)(badd
*256.0);
1806 int ia2
=(int)(aadd
*256.0);
1813 LICE_pixel_chan
*ptr
=(LICE_pixel_chan
*)p
++;
1814 _LICE_MakePixelClamp(ptr
,(ptr
[LICE_PIXEL_R
]*ir
+ir2
)>>8,
1815 (ptr
[LICE_PIXEL_G
]*ig
+ig2
)>>8,
1816 (ptr
[LICE_PIXEL_B
]*ib
+ib2
)>>8,
1817 (ptr
[LICE_PIXEL_A
]*ia
+ia2
)>>8);
1823 void LICE_ProcessRect(LICE_IBitmap
*dest
, int x
, int y
, int w
, int h
, void (*procFunc
)(LICE_pixel
*p
, void *parm
), void *parm
)
1825 if (!dest
||!procFunc
) return;
1827 if (x
<0) { w
+=x
; x
=0; }
1828 if (y
<0) { h
+=y
; y
=0; }
1830 LICE_pixel
*p
=dest
->getBits();
1831 const int sp
=dest
->getRowSpan();
1832 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1833 if (!p
|| !sp
|| w
<1 || h
< 1 || x
>= destbm_w
|| y
>= destbm_h
) return;
1835 if (w
>destbm_w
-x
) w
=destbm_w
-x
;
1836 if (h
>destbm_h
-y
) h
=destbm_h
-y
;
1838 if (dest
->isFlipped())
1840 p
+=(destbm_h
- y
- h
)*sp
;
1853 while (n
-->0) procFunc(pout
++,parm
);
1860 void LICE_FillRect(LICE_IBitmap
*dest
, int x
, int y
, int w
, int h
, LICE_pixel color
, float alpha
, int mode
)
1864 #ifndef DISABLE_LICE_EXTENSIONS
1865 if (dest
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_FILLRECT_ACCEL
))
1867 LICE_Ext_FillRect_acceldata
data(x
, y
, w
, h
, color
, alpha
, mode
);
1868 if (dest
->Extended(LICE_EXT_FILLRECT_ACCEL
, &data
)) return;
1872 if (mode
& LICE_BLIT_USE_ALPHA
) alpha
*= LICE_GETA(color
)/255.0f
;
1874 LICE_pixel
*p
=dest
->getBits();
1875 const int sp
=dest
->getRowSpan();
1877 if (x
<0) { w
+=x
; x
=0; }
1878 if (y
<0) { h
+=y
; y
=0; }
1879 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1880 if (!alpha
|| !p
|| !sp
|| w
<1 || h
< 1 || x
>= destbm_w
|| y
>= destbm_h
) return;
1882 if (w
>destbm_w
-x
) w
=destbm_w
-x
;
1883 if (h
>destbm_h
-y
) h
=destbm_h
-y
;
1885 if (dest
->isFlipped())
1887 p
+=(destbm_h
- y
- h
)*sp
;
1896 const int ia
=(int)(alpha
*256.0);
1897 // copy, alpha=1, alpha=0.5, 0.25, 0.75 optimizations
1898 if ((mode
&LICE_BLIT_MODE_MASK
)==LICE_BLIT_MODE_COPY
)
1902 _LICE_Template_Blit0
<_LICE_CombinePixelsClobberFAST
>::solidBlitFAST(p
,w
,h
,color
,sp
);
1907 // we use _LICE_CombinePixelsHalfMix2 because we pre-halve color here
1908 _LICE_Template_Blit0
<_LICE_CombinePixelsHalfMix2FAST
>::solidBlitFAST(p
,w
,h
,(color
>>1)&0x7f7f7f7f,sp
);
1913 _LICE_Template_Blit0
<_LICE_CombinePixelsQuarterMix2FAST
>::solidBlitFAST(p
,w
,h
,(color
>>2)&0x3f3f3f3f,sp
);
1918 _LICE_Template_Blit0
<_LICE_CombinePixelsThreeQuarterMix2FAST
>::solidBlitFAST(p
,w
,h
,
1919 ((color
>>1)&0x7f7f7f7f)+((color
>>2)&0x3f3f3f3f),sp
);
1924 #ifdef LICE_FAVOR_SIZE_EXTREME
1925 LICE_COMBINEFUNC blitfunc
=NULL
;
1926 #define __LICE__ACTION(comb) blitfunc=comb::doPix;
1928 #define __LICE__ACTION(comb) _LICE_Template_Blit1<comb>::solidBlit((LICE_pixel_chan*)p,w,h,LICE_GETR(color),LICE_GETG(color),LICE_GETB(color),ia,sp*sizeof(LICE_pixel))
1931 // we use __LICE_ACTION_NOSRCALPHA even though __LICE_ACTION_CONSTANTALPHA
1932 // is valid, sinc we optimized the 1.0f/0.5f cases above
1933 __LICE_ACTION_NOSRCALPHA(mode
,ia
,false);
1934 #undef __LICE__ACTION
1936 #ifdef LICE_FAVOR_SIZE_EXTREME
1937 if (blitfunc
) _LICE_Template_Blit1::solidBlit((LICE_pixel_chan
*)p
,w
,h
,LICE_GETR(color
),LICE_GETG(color
),LICE_GETB(color
),ia
,sp
*sizeof(LICE_pixel
),blitfunc
);
1941 void LICE_ClearRect(LICE_IBitmap
*dest
, int x
, int y
, int w
, int h
, LICE_pixel mask
, LICE_pixel orbits
)
1944 LICE_pixel
*p
=dest
->getBits();
1946 if (x
<0) { w
+=x
; x
=0; }
1947 if (y
<0) { h
+=y
; y
=0; }
1949 const int sp
=dest
->getRowSpan();
1950 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
1951 if (!p
|| !sp
|| w
<1 || h
< 1 || x
>= destbm_w
|| y
>= destbm_h
) return;
1953 if (w
>destbm_w
-x
) w
=destbm_w
-x
;
1954 if (h
>destbm_h
-y
) h
=destbm_h
-y
;
1956 if (dest
->isFlipped())
1958 p
+=(destbm_h
- y
- h
)*sp
;
1968 *p
= (*p
&mask
)|orbits
;
1976 LICE_pixel
LICE_GetPixel(LICE_IBitmap
*bm
, int x
, int y
)
1980 #ifndef DISABLE_LICE_EXTENSIONS
1981 if (bm
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_GETPIXEL_ACCEL
))
1983 LICE_Ext_GetPixel_acceldata
data(x
, y
);
1984 if (bm
->Extended(LICE_EXT_GETPIXEL_ACCEL
, &data
)) return data
.px
;
1988 const LICE_pixel
*px
;
1989 if (!(px
=bm
->getBits()) || x
< 0 || y
< 0 || x
>= bm
->getWidth() || y
>= bm
->getHeight()) return 0;
1990 if (bm
->isFlipped()) return px
[(bm
->getHeight()-1-y
) * bm
->getRowSpan() + x
];
1991 return px
[y
* bm
->getRowSpan() + x
];
1994 void LICE_PutPixel(LICE_IBitmap
*bm
, int x
, int y
, LICE_pixel color
, float alpha
, int mode
)
1998 #ifndef DISABLE_LICE_EXTENSIONS
1999 if (bm
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_PUTPIXEL_ACCEL
))
2001 LICE_Ext_PutPixel_acceldata
data(x
, y
, color
, alpha
, mode
);
2002 if (bm
->Extended(LICE_EXT_PUTPIXEL_ACCEL
, &data
)) return;
2007 if (!(px
=bm
->getBits()) || x
< 0 || y
< 0 || x
>= bm
->getWidth() || y
>= bm
->getHeight()) return;
2009 if (bm
->isFlipped()) px
+=x
+(bm
->getHeight()-1-y
)*bm
->getRowSpan();
2010 else px
+=x
+y
*bm
->getRowSpan();
2012 int ia
= (int)(alpha
* 256.0f
);
2013 if ((mode
&LICE_BLIT_MODE_MASK
)==LICE_BLIT_MODE_COPY
)
2022 *px
= ((*px
>>1)&0x7f7f7f7f) + ((color
>>1)&0x7f7f7f7f);
2027 *px
= ((*px
>>1)&0x7f7f7f7f) + ((*px
>>2)&0x3f3f3f3f) + ((color
>>2)&0x3f3f3f3f);
2032 *px
= ((*px
>>2)&0x3f3f3f3f) + ((color
>>1)&0x7f7f7f7f) + ((color
>>2)&0x3f3f3f3f);
2036 #define __LICE__ACTION(comb) comb::doPix((LICE_pixel_chan *)px, LICE_GETR(color),LICE_GETG(color),LICE_GETB(color),LICE_GETA(color), ia)
2037 __LICE_ACTION_NOSRCALPHA(mode
,ia
,false);
2038 #undef __LICE__ACTION
2042 #ifndef LICE_NO_BLIT_SUPPORT
2044 template<class T
> class LICE_TransformBlit_class
2047 static void blit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
2048 int dstx
, int dsty
, int dstw
, int dsth
,
2049 const T
*srcpoints
, int div_w
, int div_h
, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
2050 float alpha
, int mode
)
2052 if (!dest
|| !src
|| dstw
<1 || dsth
<1 || div_w
<2 || div_h
<2) return;
2056 double dxpos
=dstw
/(float)(div_w
-1);
2057 double dypos
=dsth
/(float)(div_h
-1);
2059 const T
*curpoints
=srcpoints
;
2060 for (y
= 0; y
< div_h
-1; y
++)
2062 int nypos
=(int)((ypos
+=dypos
) + 0.5);
2069 double iy
=1.0/(double)(nypos
-cypos
);
2070 for (x
= 0; x
< div_w
-1; x
++)
2072 int nxpos
=(int) ((xpos
+=dxpos
) + 0.5);
2076 double sx
=curpoints
[offs
];
2077 double sy
=curpoints
[offs
+1];
2078 double sw
=curpoints
[offs
+2]-sx
;
2079 double sh
=curpoints
[offs
+3]-sy
;
2082 double sxdiff
=curpoints
[offs
]-sx
;
2083 double sydiff
=curpoints
[offs
+1]-sy
;
2084 double sw3
=curpoints
[offs
+2]-curpoints
[offs
];
2085 double sh3
=curpoints
[offs
+3]-curpoints
[offs
+1];
2087 double ix
=1.0/(double)(nxpos
-cxpos
);
2090 double dsdx2
=sw3
*ix
;
2091 double dtdx2
=sh3
*ix
;
2092 double dsdy
=sxdiff
*iy
;
2093 double dtdy
=sydiff
*iy
;
2094 double dsdxdy
= (dsdx2
-dsdx
)*iy
;
2095 double dtdxdy
= (dtdx2
-dtdx
)*iy
;
2097 LICE_DeltaBlit(dest
,src
,cxpos
,cypos
,nxpos
-cxpos
,nypos
-cypos
,
2098 (float)sx
,(float)sy
,(float)sw
,(float)sh
,
2099 dsdx
,dtdx
,dsdy
,dtdy
,dsdxdy
,dtdxdy
,false,alpha
,mode
);
2111 template<class T
> class LICE_TransformBlitAlpha_class
2114 static void blit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
2115 int dstx
, int dsty
, int dstw
, int dsth
,
2116 const T
*srcpoints
, int div_w
, int div_h
, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
2119 if (!dest
|| !src
|| dstw
<1 || dsth
<1 || div_w
<2 || div_h
<2) return;
2123 double dxpos
=dstw
/(float)(div_w
-1);
2124 double dypos
=dsth
/(float)(div_h
-1);
2126 const T
*curpoints
=srcpoints
;
2127 for (y
= 0; y
< div_h
-1; y
++)
2129 int nypos
=(int)((ypos
+=dypos
)+0.5);
2136 double iy
=1.0/(double)(nypos
-cypos
);
2137 for (x
= 0; x
< div_w
-1; x
++)
2139 int nxpos
=(int) ((xpos
+=dxpos
)+0.5);
2143 double sx
=curpoints
[offs
];
2144 double sy
=curpoints
[offs
+1];
2145 double sa
=curpoints
[offs
+2];
2146 double sw
=curpoints
[offs
+3]-sx
;
2147 double sh
=curpoints
[offs
+4]-sy
;
2148 double sa2
= curpoints
[offs
+5]-sa
;
2151 double sxdiff
=curpoints
[offs
]-sx
;
2152 double sydiff
=curpoints
[offs
+1]-sy
;
2153 double sadiff
=curpoints
[offs
+2]-sa
;
2154 double sw3
=curpoints
[offs
+3]-curpoints
[offs
];
2155 double sh3
=curpoints
[offs
+4]-curpoints
[offs
+1];
2156 double sa3
=curpoints
[offs
+5]-curpoints
[offs
+2];
2158 double ix
=1.0/(double)(nxpos
-cxpos
);
2162 double dsdx2
=sw3
*ix
;
2163 double dtdx2
=sh3
*ix
;
2164 double dadx2
=sa3
*ix
;
2165 double dsdy
=sxdiff
*iy
;
2166 double dtdy
=sydiff
*iy
;
2167 double dady
=sadiff
*iy
;
2168 double dsdxdy
= (dsdx2
-dsdx
)*iy
;
2169 double dtdxdy
= (dtdx2
-dtdx
)*iy
;
2170 double dadxdy
= (dadx2
-dadx
)*iy
;
2172 LICE_DeltaBlitAlpha(dest
,src
,cxpos
,cypos
,nxpos
-cxpos
,nypos
-cypos
,
2173 (float)sx
,(float)sy
,(float)sw
,(float)sh
,
2174 dsdx
,dtdx
,dsdy
,dtdy
,dsdxdy
,dtdxdy
,false,sa
,mode
,dadx
,dady
,dadxdy
);
2186 void LICE_TransformBlit(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
2187 int dstx
, int dsty
, int dstw
, int dsth
,
2188 const float *srcpoints
, int div_w
, int div_h
, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
2189 float alpha
, int mode
)
2191 LICE_TransformBlit_class
<float>::blit(dest
,src
,dstx
,dsty
,dstw
,dsth
,srcpoints
,div_w
,div_h
,alpha
,mode
);
2193 void LICE_TransformBlit2(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
2194 int dstx
, int dsty
, int dstw
, int dsth
,
2195 const double *srcpoints
, int div_w
, int div_h
, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
2196 float alpha
, int mode
)
2198 LICE_TransformBlit_class
<double>::blit(dest
,src
,dstx
,dsty
,dstw
,dsth
,srcpoints
,div_w
,div_h
,alpha
,mode
);
2202 void LICE_TransformBlit2Alpha(LICE_IBitmap
*dest
, LICE_IBitmap
*src
,
2203 int dstx
, int dsty
, int dstw
, int dsth
,
2204 const double *srcpoints
, int div_w
, int div_h
, // srcpoints coords should be div_w*div_h*3 long, and be in source image coordinates+alpha
2207 LICE_TransformBlitAlpha_class
<double>::blit(dest
,src
,dstx
,dsty
,dstw
,dsth
,srcpoints
,div_w
,div_h
,mode
);
2211 #ifndef LICE_NO_MISC_SUPPORT
2213 void LICE_SetAlphaFromColorMask(LICE_IBitmap
*dest
, LICE_pixel color
)
2216 LICE_pixel
*p
=dest
->getBits();
2217 int h
=dest
->getHeight();
2218 int w
=dest
->getWidth();
2219 int sp
=dest
->getRowSpan();
2220 if (!p
|| w
<1 || h
<1 || sp
<1) return;
2227 if ((*p
&LICE_RGBA(255,255,255,0)) == color
) *p
&=LICE_RGBA(255,255,255,0);
2228 else *p
|=LICE_RGBA(0,0,0,255);
2236 void LICE_SimpleFill(LICE_IBitmap
*dest
, int x
, int y
, LICE_pixel newcolor
,
2237 LICE_pixel comparemask
,
2238 LICE_pixel keepmask
)
2241 int dw
=dest
->getWidth();
2242 int dh
=dest
->getHeight();
2243 int rowsize
=dest
->getRowSpan();
2244 if (x
<0||x
>=dw
||y
<0||y
>=dh
) return;
2245 LICE_pixel
*ptr
=dest
->getBits();
2249 LICE_pixel compval
=ptr
[x
]&comparemask
;
2251 for (ay
=y
;ay
<dh
; ay
++)
2253 if ((ptr
[x
]&comparemask
)!=compval
) break;
2254 ptr
[x
]=(ptr
[x
]&keepmask
)|newcolor
;
2257 for(ax
=x
+1;ax
<dw
;ax
++)
2259 if ((ptr
[ax
]&comparemask
)!=compval
) break;
2260 ptr
[ax
]=(ptr
[ax
]&keepmask
)|newcolor
;
2265 if ((ptr
[ax
]&comparemask
)!=compval
) break;
2266 ptr
[ax
]=(ptr
[ax
]&keepmask
)|newcolor
;
2271 ptr
=dest
->getBits()+rowsize
*y
;
2277 if ((ptr
[x
]&comparemask
)!=compval
) break;
2278 ptr
[x
]=(ptr
[x
]&keepmask
)|newcolor
;
2281 for(ax
=x
+1;ax
<dw
;ax
++)
2283 if ((ptr
[ax
]&comparemask
)!=compval
) break;
2284 ptr
[ax
]=(ptr
[ax
]&keepmask
)|newcolor
;
2289 if ((ptr
[ax
]&comparemask
)!=compval
) break;
2290 ptr
[ax
]=(ptr
[ax
]&keepmask
)|newcolor
;
2295 // VS6 instantiates this wrong as a template function, needs to be a template class
2296 template <class COMBFUNC
> class GlyphDrawImpl
2299 static void DrawGlyph(const LICE_pixel_chan
* srcalpha
, LICE_pixel
* destpx
, int src_w
, int src_h
, LICE_pixel color
, int span
, int src_span
, int aa
)
2301 const int r
= LICE_GETR(color
), g
= LICE_GETG(color
), b
= LICE_GETB(color
), a
= LICE_GETA(color
);
2304 for (yi
= 0; yi
< src_h
; ++yi
, srcalpha
+= src_span
, destpx
+= span
) {
2305 const LICE_pixel_chan
* tsrc
= srcalpha
;
2306 LICE_pixel
* tdest
= destpx
;
2307 for (xi
= 0; xi
< src_w
; ++xi
, ++tsrc
, ++tdest
) {
2308 const LICE_pixel_chan v
= *tsrc
;
2309 if (v
) { // glyphs should be expected to have a lot of "holes"
2310 COMBFUNC::doPix((LICE_pixel_chan
*) tdest
, r
, g
, b
, a
, v
*aa
/256);
2317 void LICE_DrawGlyphEx(LICE_IBitmap
* dest
, int x
, int y
, LICE_pixel color
, const LICE_pixel_chan
* alphas
, int glyph_w
, int glyph_span
, int glyph_h
, float alpha
, int mode
)
2321 #ifndef DISABLE_LICE_EXTENSIONS
2322 if (dest
->Extended(LICE_EXT_SUPPORTS_ID
, (void*) LICE_EXT_DRAWGLYPH_ACCEL
) && glyph_w
== glyph_span
)
2324 LICE_Ext_DrawGlyph_acceldata
data(x
, y
, color
, alphas
, glyph_w
, glyph_h
, alpha
, mode
);
2325 if (dest
->Extended(LICE_EXT_DRAWGLYPH_ACCEL
, &data
)) return;
2329 const int ia
= (int)(alpha
*256.0f
);
2331 int src_x
= 0, src_y
= 0, src_w
= glyph_w
, src_h
= glyph_h
;
2332 if (x
<= -src_w
|| y
<= -src_h
) return;
2345 const int destbm_w
= dest
->getWidth(), destbm_h
= dest
->getHeight();
2346 if (src_w
< 0 || src_h
< 0 || x
>= destbm_w
|| y
>= destbm_h
) return;
2348 if (src_h
> destbm_h
-y
) src_h
= destbm_h
-y
;
2349 if (src_w
> destbm_w
-x
) src_w
= destbm_w
-x
;
2351 if (src_w
< 1 || src_h
< 1) return;
2354 LICE_pixel
* destpx
= dest
->getBits();
2355 int span
= dest
->getRowSpan();
2356 if (dest
->isFlipped()) {
2357 destpx
+= (destbm_h
-y
-1)*span
+x
;
2361 destpx
+= y
*dest
->getRowSpan()+x
;
2364 const LICE_pixel_chan
* srcalpha
= alphas
+src_y
*glyph_span
+src_x
;
2366 #define __LICE__ACTION(COMBFUNC) GlyphDrawImpl<COMBFUNC>::DrawGlyph(srcalpha,destpx, src_w, src_h, color,span,glyph_span,ia)
2367 __LICE_ACTION_NOSRCALPHA(mode
, ia
, false);
2368 #undef __LICE__ACTION
2371 void LICE_DrawGlyph(LICE_IBitmap
* dest
, int x
, int y
, LICE_pixel color
, const LICE_pixel_chan
* alphas
, int glyph_w
, int glyph_h
, float alpha
, int mode
)
2373 LICE_DrawGlyphEx(dest
,x
,y
,color
,alphas
,glyph_w
,glyph_w
,glyph_h
,alpha
,mode
);
2376 void LICE_HalveBlitAA(LICE_IBitmap
*dest
, LICE_IBitmap
*src
)
2378 if (!dest
||!src
) return;
2379 int w
= dest
->getWidth();
2380 if (w
> src
->getWidth()/2) w
=src
->getWidth()/2;
2381 int h
= dest
->getHeight();
2382 if (h
> src
->getHeight()/2) h
=src
->getHeight()/2;
2383 int src_span
= src
->getRowSpan();
2384 int dest_span
= dest
->getRowSpan();
2385 const LICE_pixel
*srcptr
= src
->getBits();
2386 LICE_pixel
*destptr
= dest
->getBits();
2390 const LICE_pixel
*sp
= srcptr
;
2391 const LICE_pixel
*sp2
= srcptr
+src_span
;
2392 LICE_pixel
*dp
= destptr
;
2395 // this is begging for SSE intrinsics, but we never use this function so leave it as-is :)
2397 // perhaps we should use more precision rather than chopping each src pixel to 6 bits, but oh well
2398 while (x
--) // unroll 2px at a time, about 5% faster on core2 and ICC
2400 int r1
=((sp
[0]>>2)&0x3f3f3f3f);
2401 int r2
=((sp
[2]>>2)&0x3f3f3f3f);
2402 r1
+= ((sp
[1]>>2)&0x3f3f3f3f);
2403 r2
+= ((sp
[3]>>2)&0x3f3f3f3f);
2405 ((sp2
[0]>>2)&0x3f3f3f3f) +
2406 ((sp2
[1]>>2)&0x3f3f3f3f);
2408 ((sp2
[2]>>2)&0x3f3f3f3f) +
2409 ((sp2
[3]>>2)&0x3f3f3f3f);
2417 ((sp
[0]>>2)&0x3f3f3f3f) +
2418 ((sp
[1]>>2)&0x3f3f3f3f) +
2419 ((sp2
[0]>>2)&0x3f3f3f3f) +
2420 ((sp2
[1]>>2)&0x3f3f3f3f);
2427 #endif // LICE_NO_MISC_SUPPORT
2429 int LICE_BitmapCmp(LICE_IBitmap
* a
, LICE_IBitmap
* b
, int *coordsOut
)
2431 return LICE_BitmapCmpEx(a
,b
,LICE_RGBA(255,255,255,255),coordsOut
);
2434 int LICE_BitmapCmpEx(LICE_IBitmap
* a
, LICE_IBitmap
* b
, LICE_pixel mask
, int *coordsOut
)
2437 if (!a
&& b
) return -1;
2438 if (a
&& !b
) return 1;
2442 int aw
= a
->getWidth(), bw
= b
->getWidth();
2443 if (aw
!= bw
) return bw
-aw
;
2444 int ah
= a
->getHeight(), bh
= b
->getHeight();
2445 if (ah
!= bh
) return bh
-ah
;
2448 const LICE_pixel
*px1
= a
->getBits();
2449 const LICE_pixel
*px2
= b
->getBits();
2450 int span1
= a
->getRowSpan();
2451 int span2
= b
->getRowSpan();
2466 if (mask
== LICE_RGBA(255,255,255,255))
2467 for (y
=0; y
< ah
; y
++)
2469 int a
= memcmp(px1
,px2
,aw
*sizeof(LICE_pixel
));
2475 for (y
=0; y
< ah
; y
++)
2477 const LICE_pixel
*ptr1
= px1
, *ptr2
= px2
;
2480 if ((*ptr1
++ ^ *ptr2
++) & mask
) return true;
2489 // find first row that differs
2490 for (y
=0; y
< ah
; y
++)
2493 for (x
=0;x
<aw
&& !((px1
[x
]^px2
[x
])&mask
);x
++);
2501 memset(coordsOut
,0,4*sizeof(int));
2502 return 0; // no differences
2507 // scan right edge of top differing row
2508 for (x
=aw
-1;x
>minx
&& !((px1
[x
]^px2
[x
])&mask
);x
--);
2511 // find last row that differs
2512 px1
+=span1
* (ah
-1-y
);
2513 px2
+=span2
* (ah
-1-y
);
2514 for (y
= ah
-1; y
> miny
; y
--)
2518 for (x
=0;x
<aw
&& !((px1
[x
]^px2
[x
])&mask
);x
++);
2527 if (x
< minx
) minx
=x
;
2528 // scan right edge of bottom row that differs
2529 for (x
=aw
-1;x
>maxx
&& !((px1
[x
]^px2
[x
])&mask
);x
--);
2534 // find min/max x that differ
2535 px1
+=span1
* (miny
+1-y
);
2536 px2
+=span2
* (miny
+1-y
);
2537 for (y
=miny
+1;y
<maxy
&& (minx
>0 || maxx
<aw
-1);y
++)
2540 for (x
=0;x
<minx
&& !((px1
[x
]^px2
[x
])&mask
);x
++);
2542 for (x
=aw
-1;x
>maxx
&& !((px1
[x
]^px2
[x
])&mask
);x
--);
2551 coordsOut
[2]=maxx
-minx
+1;
2552 coordsOut
[3]=maxy
-miny
+1;
2560 unsigned short _LICE_RGB2HSV_invtab
[256]={ // 65536/idx - 1
2561 0, 0xffff, 0x7fff, 0x5554, 0x3fff, 0x3332, 0x2aa9, 0x2491,
2562 0x1fff, 0x1c70, 0x1998, 0x1744, 0x1554, 0x13b0, 0x1248, 0x1110,
2563 0x0fff, 0x0f0e, 0x0e37, 0x0d78, 0x0ccb, 0x0c2f, 0x0ba1, 0x0b20,
2564 0x0aa9, 0x0a3c, 0x09d7, 0x097a, 0x0923, 0x08d2, 0x0887, 0x0841,
2565 0x07ff, 0x07c0, 0x0786, 0x074f, 0x071b, 0x06ea, 0x06bb, 0x068f,
2566 0x0665, 0x063d, 0x0617, 0x05f3, 0x05d0, 0x05af, 0x058f, 0x0571,
2567 0x0554, 0x0538, 0x051d, 0x0504, 0x04eb, 0x04d3, 0x04bc, 0x04a6,
2568 0x0491, 0x047c, 0x0468, 0x0455, 0x0443, 0x0431, 0x0420, 0x040f,
2569 0x03ff, 0x03ef, 0x03df, 0x03d1, 0x03c2, 0x03b4, 0x03a7, 0x039a,
2570 0x038d, 0x0380, 0x0374, 0x0368, 0x035d, 0x0352, 0x0347, 0x033c,
2571 0x0332, 0x0328, 0x031e, 0x0314, 0x030b, 0x0302, 0x02f9, 0x02f0,
2572 0x02e7, 0x02df, 0x02d7, 0x02cf, 0x02c7, 0x02bf, 0x02b8, 0x02b0,
2573 0x02a9, 0x02a2, 0x029b, 0x0294, 0x028e, 0x0287, 0x0281, 0x027b,
2574 0x0275, 0x026f, 0x0269, 0x0263, 0x025d, 0x0258, 0x0252, 0x024d,
2575 0x0248, 0x0242, 0x023d, 0x0238, 0x0233, 0x022f, 0x022a, 0x0225,
2576 0x0221, 0x021c, 0x0218, 0x0213, 0x020f, 0x020b, 0x0207, 0x0203,
2577 0x01ff, 0x01fb, 0x01f7, 0x01f3, 0x01ef, 0x01eb, 0x01e8, 0x01e4,
2578 0x01e0, 0x01dd, 0x01d9, 0x01d6, 0x01d3, 0x01cf, 0x01cc, 0x01c9,
2579 0x01c6, 0x01c2, 0x01bf, 0x01bc, 0x01b9, 0x01b6, 0x01b3, 0x01b1,
2580 0x01ae, 0x01ab, 0x01a8, 0x01a5, 0x01a3, 0x01a0, 0x019d, 0x019b,
2581 0x0198, 0x0196, 0x0193, 0x0191, 0x018e, 0x018c, 0x0189, 0x0187,
2582 0x0185, 0x0182, 0x0180, 0x017e, 0x017c, 0x0179, 0x0177, 0x0175,
2583 0x0173, 0x0171, 0x016f, 0x016d, 0x016b, 0x0169, 0x0167, 0x0165,
2584 0x0163, 0x0161, 0x015f, 0x015d, 0x015b, 0x0159, 0x0157, 0x0156,
2585 0x0154, 0x0152, 0x0150, 0x014f, 0x014d, 0x014b, 0x0149, 0x0148,
2586 0x0146, 0x0145, 0x0143, 0x0141, 0x0140, 0x013e, 0x013d, 0x013b,
2587 0x013a, 0x0138, 0x0137, 0x0135, 0x0134, 0x0132, 0x0131, 0x012f,
2588 0x012e, 0x012d, 0x012b, 0x012a, 0x0128, 0x0127, 0x0126, 0x0124,
2589 0x0123, 0x0122, 0x0120, 0x011f, 0x011e, 0x011d, 0x011b, 0x011a,
2590 0x0119, 0x0118, 0x0117, 0x0115, 0x0114, 0x0113, 0x0112, 0x0111,
2591 0x0110, 0x010e, 0x010d, 0x010c, 0x010b, 0x010a, 0x0109, 0x0108,
2592 0x0107, 0x0106, 0x0105, 0x0104, 0x0103, 0x0102, 0x0101, 0x0100,
2596 #endif//__LICE_CPP_IMPLEMENTED__