1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "../../../include/fxge/fx_ge.h"
6//#define _SKIA_SUPPORT_
7#if defined(_SKIA_SUPPORT_)
8#include "../../../include/fxcodec/fx_codec.h"
9#include "SkBlitter.h"
10#include "fx_skia_blitter_new.h"
11	// We use our own renderer here to make it simple
12	void CFX_SkiaRenderer::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
13	{
14		FXSYS_assert(m_Alpha);
15		if (m_pOriDevice == NULL && composite_span == NULL) return;
16		if (y < m_ClipBox.top || y >= m_ClipBox.bottom) return;
17		while (1)
18		{
19			int width = runs[0];
20			SkASSERT(width >= 0);
21			if (width <= 0)
22				return;
23			unsigned aa = antialias[0];
24			if (aa)
25				(this->*composite_span)(m_pDestScan, m_pOriScan, 0, x, width, y, aa, m_ClipBox.top, m_ClipBox.left, m_ClipBox.right, m_pClipScan, m_pDestExtraAlphaScan);
26			runs += width;
27			antialias += width;
28			x += width;
29		}
30	}
31
32	void CFX_SkiaRenderer::blitH(int x, int y, int width)
33	{
34		FXSYS_assert(m_Alpha && width);
35		if (y < m_ClipBox.top || y >= m_ClipBox.bottom) return;
36		(this->*composite_span)(m_pDestScan, m_pOriScan, 0, x, width, y, 255, m_ClipBox.top, m_ClipBox.left, m_ClipBox.right, m_pClipScan, m_pDestExtraAlphaScan);
37	}
38
39	void CFX_SkiaRenderer::blitV(int x, int y, int height, SkAlpha alpha)
40	{
41		FXSYS_assert(m_Alpha && alpha);
42		if (alpha == 255) {
43			this->blitRect(x, y, 1, height);
44		} else {
45			int16_t runs[2];
46			runs[0] = 1;
47			runs[1] = 0;
48			while (--height >= 0) {
49				if (y >= m_ClipBox.bottom)
50					return;
51				this->blitAntiH(x, y ++, &alpha, runs);
52			}
53		}
54	}
55	void CFX_SkiaRenderer::blitRect(int x, int y, int width, int height)
56	{
57		FXSYS_assert(m_Alpha && width);
58		while (--height >= 0){
59			if (y >= m_ClipBox.bottom)
60				return;
61			blitH(x, y ++, width);
62		}
63	}
64
65	void CFX_SkiaRenderer::blitAntiRect(int x, int y, int width, int height,
66                             SkAlpha leftAlpha, SkAlpha rightAlpha)
67	{
68		blitV(x++, y, height, leftAlpha);
69		if (width > 0) {
70			blitRect(x, y, width, height);
71			x += width;
72		}
73		blitV(x, y, height, rightAlpha);
74	}
75	/*---------------------------------------------------------------------------------------------------*/
76	void CFX_SkiaRenderer::CompositeSpan1bpp_0(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
77			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
78			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
79			FX_LPBYTE dest_extra_alpha_scan)
80	{
81		ASSERT(!m_bRgbByteOrder);
82		ASSERT(!m_pDevice->IsCmykImage());
83		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left/8;
84		int col_start = span_left < clip_left ? clip_left - span_left : 0;
85		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
86		if (col_end < col_start) return; // do nothing.
87		dest_scan += col_start/8;
88
89		int index = 0;
90		if (m_pDevice->GetPalette() == NULL)
91			index = ((FX_BYTE)m_Color == 0xff) ? 1 : 0;
92		else {
93			for (int i = 0; i < 2; i ++)
94				if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color)
95					index = i;
96		}
97		FX_LPBYTE dest_scan1 = dest_scan;
98		int src_alpha = m_Alpha * cover_scan / 255;
99		for (int col = col_start; col < col_end; col ++) {
100			if (src_alpha) {
101				if (!index)
102					*dest_scan1 &= ~(1 << (7 - (col+span_left)%8));
103				else
104					*dest_scan1|= 1 << (7 - (col+span_left)%8);
105			}
106			dest_scan1 = dest_scan+(span_left%8+col-col_start+1)/8;
107		}
108	}
109	void CFX_SkiaRenderer::CompositeSpan1bpp_4(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
110			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
111			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
112			FX_LPBYTE dest_extra_alpha_scan)
113	{
114		ASSERT(!m_bRgbByteOrder);
115		ASSERT(!m_pDevice->IsCmykImage());
116		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left/8;
117		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
118		int col_start = span_left < clip_left ? clip_left - span_left : 0;
119		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
120		if (col_end < col_start) return; // do nothing.
121		dest_scan += col_start/8;
122
123		int index = 0;
124		if (m_pDevice->GetPalette() == NULL)
125			index = ((FX_BYTE)m_Color == 0xff) ? 1 : 0;
126		else {
127			for (int i = 0; i < 2; i ++)
128				if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color)
129					index = i;
130		}
131		FX_LPBYTE dest_scan1 = dest_scan;
132		int src_alpha = m_Alpha * cover_scan / 255;
133		for (int col = col_start; col < col_end; col ++) {
134			int src_alpha1 = src_alpha * clip_scan[col] / 255;
135			if (src_alpha1) {
136				if (!index)
137					*dest_scan1 &= ~(1 << (7 - (col+span_left)%8));
138				else
139					*dest_scan1|= 1 << (7 - (col+span_left)%8);
140			}
141			dest_scan1 = dest_scan+(span_left%8+col-col_start+1)/8;
142		}
143	}
144	/*-----------------------------------------------------------------------------------------------------*/
145	void CFX_SkiaRenderer::CompositeSpanGray_2(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
146			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
147			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
148			FX_LPBYTE dest_extra_alpha_scan)
149	{
150		ASSERT(!m_pDevice->IsCmykImage());
151		ASSERT(!m_bRgbByteOrder);
152		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left;
153		int col_start = span_left < clip_left ? clip_left - span_left : 0;
154		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
155		if (col_end < col_start) return; // do nothing.
156		dest_scan += col_start;
157		if (cover_scan == 255 && m_Alpha == 255) {
158			FXSYS_memset32(dest_scan, FXARGB_MAKE(m_Gray, m_Gray, m_Gray, m_Gray), col_end - col_start);
159			return;
160		}
161		int src_alpha = m_Alpha * cover_scan / 255;
162		for (int col = col_start; col < col_end; col ++) {
163			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
164			dest_scan++;
165		}
166	}
167	void CFX_SkiaRenderer::CompositeSpanGray_3(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
168			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
169			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
170			FX_LPBYTE dest_extra_alpha_scan)
171	{
172		ASSERT(!m_pDevice->IsCmykImage());
173		ASSERT(!m_bRgbByteOrder);
174		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left;
175		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + span_left;
176		int col_start = span_left < clip_left ? clip_left - span_left : 0;
177		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
178		if (col_end < col_start) return; // do nothing.
179		dest_scan += col_start;
180		ori_scan += col_start;
181		if (m_Alpha == 255 && cover_scan == 255) {
182			FXSYS_memset32(dest_scan, FXARGB_MAKE(m_Gray, m_Gray, m_Gray, m_Gray), col_end - col_start);
183		} else {
184			int src_alpha = m_Alpha;
185#if 1
186			for (int col = col_start; col < col_end; col ++) {
187				int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
188				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan);
189				dest_scan ++;
190			}
191#else
192			if (m_bFullCover) {
193				if (src_alpha == 255) {
194					FXSYS_memset(dest_scan, FXARGB_MAKE(m_Gray, m_Gray, m_Gray, m_Gray), col_end - col_start);
195					return;
196				}
197				for (int col = col_start; col < col_end; col ++)
198					*dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
199			} else {
200				for (int col = col_start; col < col_end; col ++) {
201					int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
202					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan);
203					dest_scan++;
204				}
205			}
206#endif
207		}
208	}
209
210	void CFX_SkiaRenderer::CompositeSpanGray_6(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
211			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
212			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
213			FX_LPBYTE dest_extra_alpha_scan)
214	{
215		ASSERT(!m_bRgbByteOrder);
216		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left;
217		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
218		int col_start = span_left < clip_left ? clip_left - span_left : 0;
219		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
220		if (col_end < col_start) return; // do nothing.
221		dest_scan += col_start;
222		int src_alpha = m_Alpha * cover_scan / 255;
223		for (int col = col_start; col < col_end; col ++) {
224			int src_alpha1 = src_alpha * clip_scan[col] / 255;
225			if (!src_alpha1) {
226				dest_scan ++;
227				continue;
228			}
229			if (src_alpha1 == 255)
230				*dest_scan++ = m_Gray;
231			else {
232				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha1);
233				dest_scan ++;
234			}
235		}
236	}
237
238	void CFX_SkiaRenderer::CompositeSpanGray_7(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
239			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
240			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
241			FX_LPBYTE dest_extra_alpha_scan)
242	{
243		ASSERT(!m_pDevice->IsCmykImage());
244		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left;
245		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + span_left;
246		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
247		int col_start = span_left < clip_left ? clip_left - span_left : 0;
248		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
249		if (col_end < col_start) return; // do nothing.
250		dest_scan += col_start;
251		ori_scan += col_start;
252#if 1
253		for (int col = col_start; col < col_end; col ++) {
254			int src_alpha = m_Alpha * clip_scan[col] / 255;
255			if (src_alpha == 255 && cover_scan == 255) {
256				*dest_scan++ = m_Gray;
257				ori_scan++;
258				continue;
259			}
260			int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
261			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan);
262			dest_scan++;
263		}
264
265#else
266		if (m_bFullCover) {
267			for (int col = col_start; col < col_end; col ++) {
268				int src_alpha = m_Alpha * clip_scan[col] / 255;
269				if (!src_alpha) {
270					dest_scan++;
271					ori_scan++;
272					continue;
273				}
274				if (src_alpha == 255){
275					*dest_scan++ = m_Gray;
276					ori_scan++;
277					continue;
278				}
279				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
280			}
281		} else {
282			for (int col = col_start; col < col_end; col ++) {
283				int src_alpha = m_Alpha * clip_scan[col] / 255;
284				if (src_alpha == 255 && cover_scan == 255) {
285					*dest_scan++ = m_Gray;
286					ori_scan++;
287					continue;
288				}
289				int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha);
290				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan);
291				dest_scan++;
292			}
293		}
294#endif
295	}
296	/*--------------------------------------------------------------------------------------------------*/
297
298	void CFX_SkiaRenderer::CompositeSpanARGB_2(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
299			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
300			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
301			FX_LPBYTE dest_extra_alpha_scan)
302	{
303		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
304		int col_start = span_left < clip_left ? clip_left - span_left : 0;
305		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
306		if (col_end < col_start) return; // do nothing.
307		dest_scan += col_start<<2;
308		if (m_Alpha == 255 && cover_scan == 255) {
309			FXSYS_memset32(dest_scan, m_Color, (col_end - col_start)<<2);
310			return;
311		}
312		int src_alpha;
313#if 0
314		if (m_bFullCover) {
315			if (m_Alpha == 255) {
316				FXSYS_memset32(dest_scan, m_Color, (col_end - col_start)<<2);
317				return;
318			}
319		}
320		else
321#endif
322			src_alpha = m_Alpha * cover_scan / 255;
323		for (int col = col_start; col < col_end; col ++) {
324			// Dest format: Argb
325			// calculate destination alpha (it's union of source and dest alpha)
326			if (dest_scan[3] == 0) {
327				dest_scan[3] = src_alpha;
328				*dest_scan++ = m_Blue;
329				*dest_scan++ = m_Green;
330				*dest_scan = m_Red;
331				dest_scan += 2;
332				continue;
333			}
334			FX_BYTE dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
335			dest_scan[3] = dest_alpha;
336			int alpha_ratio = src_alpha*255/dest_alpha;
337			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
338			dest_scan ++;
339			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
340			dest_scan ++;
341			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
342			dest_scan += 2;
343		}
344	}
345
346	void CFX_SkiaRenderer::CompositeSpanARGB_3(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
347			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
348			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
349			FX_LPBYTE dest_extra_alpha_scan)
350	{
351		ASSERT(!m_pDevice->IsCmykImage());
352		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
353		//ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + (span_left<<2);
354		int col_start = span_left < clip_left ? clip_left - span_left : 0;
355		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
356		if (col_end < col_start) return; // do nothing.
357		dest_scan += col_start << 2;
358		//ori_scan += col_start << 2;
359
360		if (m_Alpha == 255 && cover_scan == 255){
361			FXSYS_memset32(dest_scan, m_Color, (col_end - col_start)<<2);
362			return;
363		}
364		if (cover_scan == 255) {
365			int dst_color = (0x00ffffff&m_Color)|(m_Alpha<<24);
366			FXSYS_memset32(dest_scan, dst_color, (col_end - col_start)<<2);
367			return;
368		}
369		// Do not need origin bitmap, because of merge in pure transparent background
370		int src_alpha_covered = m_Alpha * cover_scan / 255;
371		for (int col = col_start; col < col_end; col ++)
372		{
373			// shortcut
374			if (dest_scan[3] == 0) {
375				dest_scan[3] = src_alpha_covered;
376				*dest_scan ++ = m_Blue;
377				*dest_scan ++ = m_Green;
378				*dest_scan = m_Red;
379				dest_scan += 2;
380				continue;
381			}
382			// We should do alpha transition and color transition
383			// alpha fg          color fg
384			// alpha bg          color bg
385			// alpha cover       color cover
386			dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], m_Alpha, cover_scan);
387			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover_scan);
388			dest_scan ++;
389			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover_scan);
390			dest_scan ++;
391			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover_scan);
392			dest_scan += 2;
393		}
394	}
395	void CFX_SkiaRenderer::CompositeSpanARGB_6(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
396			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
397			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
398			FX_LPBYTE dest_extra_alpha_scan)
399	{
400		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
401		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
402		int col_start = span_left < clip_left ? clip_left - span_left : 0;
403		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
404		if (col_end < col_start) return; // do nothing.
405		dest_scan += col_start << 2;
406#if 1
407		int src_alpha = m_Alpha * cover_scan / 255;
408		for (int col = col_start; col < col_end; col ++) {
409			int src_alpha1 = src_alpha* clip_scan[col] / 255;
410			if (!src_alpha1) {
411				dest_scan += 4;
412				continue;
413			}
414			if (src_alpha1 == 255) {
415				*(FX_DWORD*)dest_scan = m_Color;
416				dest_scan += 4;
417			} else {
418				// Dest format: Argb
419				// calculate destination alpha (it's union of source and dest alpha)
420				if (dest_scan[3] == 0) {
421					dest_scan[3] = src_alpha1;
422					*dest_scan++ = m_Blue;
423					*dest_scan++ = m_Green;
424					*dest_scan = m_Red;
425					dest_scan += 2;
426					continue;
427				}
428				FX_BYTE dest_alpha = dest_scan[3] + src_alpha1 - dest_scan[3] * src_alpha1 / 255;
429				dest_scan[3] = dest_alpha;
430				int alpha_ratio = src_alpha1*255/dest_alpha;
431				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
432				dest_scan ++;
433				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
434				dest_scan ++;
435				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
436				dest_scan += 2;
437			}
438		}
439#else
440		if (m_bFullCover) {
441			for (int col = col_start; col < col_end; col ++) {
442				int src_alpha = m_Alpha * clip_scan[col] / 255;
443				if (!src_alpha) {
444					dest_scan += 4;
445					continue;
446				}
447				if (src_alpha == 255){
448					*(FX_DWORD*)dest_scan = m_Color;
449					dest_scan += 4;
450					continue;
451				} else {
452					// Dest format: Argb
453					// calculate destination alpha (it's union of source and dest alpha)
454					if (dest_scan[3] == 0) {
455						dest_scan[3] = src_alpha;
456						*dest_scan++ = m_Blue;
457						*dest_scan++ = m_Green;
458						*dest_scan = m_Red;
459						dest_scan += 2;
460						continue;
461					}
462					FX_BYTE dest_alpha = dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
463					dest_scan[3] = dest_alpha;
464					int alpha_ratio = src_alpha*255/dest_alpha;
465					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
466					dest_scan ++;
467					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
468					dest_scan ++;
469					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
470					dest_scan += 2;
471				}
472			}
473		} else {
474			int src_alpha = m_Alpha * cover_scan / 255;
475			for (int col = col_start; col < col_end; col ++) {
476				int src_alpha1 = src_alpha* clip_scan[col] / 255;
477				if (!src_alpha1) {
478					dest_scan += 4;
479					continue;
480				}
481				if (src_alpha1 == 255) {
482					*(FX_DWORD*)dest_scan = m_Color;
483					dest_scan += 4;
484				} else {
485					// Dest format: Argb
486					// calculate destination alpha (it's union of source and dest alpha)
487					if (dest_scan[3] == 0) {
488						dest_scan[3] = src_alpha1;
489						*dest_scan++ = m_Blue;
490						*dest_scan++ = m_Green;
491						*dest_scan = m_Red;
492						dest_scan += 2;
493						continue;
494					}
495					FX_BYTE dest_alpha = dest_scan[3] + src_alpha1 - dest_scan[3] * src_alpha1 / 255;
496					dest_scan[3] = dest_alpha;
497					int alpha_ratio = src_alpha1*255/dest_alpha;
498					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
499					dest_scan ++;
500					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
501					dest_scan ++;
502					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
503					dest_scan += 2;
504				}
505			}
506		}
507#endif
508	}
509
510	void CFX_SkiaRenderer::CompositeSpanARGB_7(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
511			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
512			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
513			FX_LPBYTE dest_extra_alpha_scan)
514	{
515		ASSERT(!m_pDevice->IsCmykImage());
516		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
517		//ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + (span_left<<2);
518		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
519		int col_start = span_left < clip_left ? clip_left - span_left : 0;
520		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
521		if (col_end < col_start) return; // do nothing.
522		dest_scan += col_start << 2;
523		//ori_scan += col_start << 2;
524		// Do not need origin bitmap, because of merge in pure transparent background
525		for (int col = col_start; col < col_end; col ++)
526		{
527			int src_alpha = m_Alpha * clip_scan[col] / 255;
528			int src_alpha_covered = src_alpha * cover_scan / 255;
529			// shortcut
530			if (src_alpha_covered == 0){
531				dest_scan += 4;
532				continue;
533			}
534			// shortcut
535			if (cover_scan == 255 || dest_scan[3] == 0)
536			{
537				// origin alpha always zero, just get src alpha
538				dest_scan[3] = src_alpha_covered;
539				*dest_scan ++ = m_Blue;
540				*dest_scan ++ = m_Green;
541				*dest_scan = m_Red;
542				dest_scan += 2;
543				continue;
544			}
545			// We should do alpha transition and color transition
546			// alpha fg          color fg
547			// alpha bg          color bg
548			// alpha cover       color cover
549			dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover_scan);
550			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover_scan);
551			dest_scan ++;
552			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover_scan);
553			dest_scan ++;
554			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover_scan);
555			dest_scan += 2;
556		}
557	}
558
559	/*-----------------------------------------------------------------------------------------------------------*/
560	void CFX_SkiaRenderer::CompositeSpanRGB32_2(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
561			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
562			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
563			FX_LPBYTE dest_extra_alpha_scan)
564	{
565		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
566		int col_start = span_left < clip_left ? clip_left - span_left : 0;
567		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
568		if (col_end < col_start) return; // do nothing.
569		dest_scan += (col_start << 2);
570		if (m_Alpha == 255 && cover_scan == 255) {
571			FXSYS_memset32(dest_scan, m_Color, (col_end - col_start)<<2);
572			return;
573		}
574		int src_alpha;
575#if 0
576		if (m_bFullCover)
577			src_alpha = m_Alpha;
578		else
579#endif
580			src_alpha = m_Alpha * cover_scan / 255;
581		for (int col = col_start; col < col_end; col ++) {
582			// Dest format:  Rgb32
583			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
584			dest_scan ++;
585			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
586			dest_scan ++;
587			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
588			dest_scan += 2;
589		}
590	}
591	void CFX_SkiaRenderer::CompositeSpanRGB32_3(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
592			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
593			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
594			FX_LPBYTE dest_extra_alpha_scan)
595	{
596		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
597		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + (span_left<<2);
598		int col_start = span_left < clip_left ? clip_left - span_left : 0;
599		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
600		if (col_end < col_start) return; // do nothing.
601		dest_scan += col_start << 2;
602		ori_scan += col_start << 2;
603		if (m_Alpha == 255 && cover_scan == 255) {
604			FXSYS_memset32(dest_scan, m_Color, (col_end - col_start)<<2);
605			return;
606		}
607		int src_alpha = m_Alpha;
608		for (int col = col_start; col < col_end; col ++) {
609#if 0
610			if (m_bFullCover) {
611				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
612				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
613				*dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
614				dest_scan += 2; ori_scan += 2;
615				continue;
616			}
617#endif
618			int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
619			int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
620			int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
621			ori_scan += 2;
622			*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
623 			dest_scan ++;
624			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
625 			dest_scan ++;
626			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
627			dest_scan += 2;
628		}
629	}
630	void CFX_SkiaRenderer::CompositeSpanRGB32_6(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
631			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
632			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
633			FX_LPBYTE dest_extra_alpha_scan)
634	{
635		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
636		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
637		int col_start = span_left < clip_left ? clip_left - span_left : 0;
638		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
639		if (col_end < col_start) return; // do nothing.
640		dest_scan += col_start << 2;
641#if 1
642		int src_alpha = m_Alpha * cover_scan / 255;
643		for (int col = col_start; col < col_end; col ++) {
644			int src_alpha1 = src_alpha * clip_scan[col] / 255;
645			if (!src_alpha1) {
646				dest_scan += 4;
647				continue;
648			}
649			if (src_alpha1 == 255) {
650				*(FX_DWORD*)dest_scan = m_Color;
651				dest_scan += 4;
652			} else {
653				// Dest format: Rgb or Rgb32
654				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha1);
655				dest_scan ++;
656				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha1);
657				dest_scan ++;
658				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha1);
659				dest_scan += 2;
660			}
661		}
662#else
663		if (m_bFullCover) {
664			for (int col = col_start; col < col_end; col ++) {
665				int src_alpha = m_Alpha * clip_scan[col] / 255;
666				if (!src_alpha) {
667					dest_scan += 4;
668					continue;
669				}
670				if (src_alpha == 255) {
671					*(FX_DWORD*)dest_scan = m_Color;
672					dest_scan += 4;
673				} else {
674					// Dest format: Rgb or Rgb32
675					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
676					dest_scan ++;
677					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
678					dest_scan ++;
679					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
680					dest_scan += 2;
681				}
682			}
683		} else {
684			// Rgb32
685			int src_alpha = m_Alpha * cover_scan / 255;
686			for (int col = col_start; col < col_end; col ++) {
687				int src_alpha1 = src_alpha * clip_scan[col] / 255;
688				if (!src_alpha1) {
689					dest_scan += 4;
690					continue;
691				}
692				if (src_alpha1 == 255) {
693					*(FX_DWORD*)dest_scan = m_Color;
694					dest_scan += 4;
695				} else {
696					// Dest format: Rgb or Rgb32
697					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha1);
698					dest_scan ++;
699					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha1);
700					dest_scan ++;
701					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha1);
702					dest_scan += 2;
703				}
704			}
705		}
706#endif
707	}
708	void CFX_SkiaRenderer::CompositeSpanRGB32_7(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
709			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
710			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
711			FX_LPBYTE dest_extra_alpha_scan)
712	{
713		ASSERT(!m_pDevice->IsCmykImage());
714		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + (span_left<<2);
715		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + (span_left<<2);
716		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
717		int col_start = span_left < clip_left ? clip_left - span_left : 0;
718		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
719		if (col_end < col_start) return; // do nothing.
720		dest_scan += col_start << 2;
721		ori_scan += col_start << 2;
722#if 1
723		for (int col = col_start; col < col_end; col ++) {
724			int src_alpha = m_Alpha * clip_scan[col] / 255;
725			if (src_alpha == 255 && cover_scan == 255) {
726				*(FX_DWORD*)dest_scan = m_Color;
727				dest_scan += 4;
728				ori_scan += 4;
729				continue;
730			}
731			int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
732			int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
733			int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
734			ori_scan += 2;
735			*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
736 			dest_scan ++;
737			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
738 			dest_scan ++;
739			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
740			dest_scan += 2;
741		}
742#else
743		if (m_bFullCover) {
744			for (int col = col_start; col < col_end; col ++) {
745				int src_alpha = m_Alpha * clip_scan[col] / 255;
746				if (!src_alpha) {
747					*(FX_DWORD*)dest_scan = *(FX_DWORD*)ori_scan;
748					dest_scan += 4;
749					ori_scan += 4;
750					continue;
751				}
752				if (src_alpha == 255) {
753					*(FX_DWORD*)dest_scan = m_Color;
754					dest_scan += 4;
755					ori_scan += 4;
756					continue;
757				}
758				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
759				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
760				*dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
761				dest_scan += 2; ori_scan += 2;
762			}
763		} else {
764			for (int col = col_start; col < col_end; col ++) {
765				int src_alpha = m_Alpha * clip_scan[col] / 255;
766				if (src_alpha == 255 && cover_scan == 255) {
767					*(FX_DWORD*)dest_scan = m_Color;
768					dest_scan += 4;
769					ori_scan += 4;
770					continue;
771				}
772				int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
773				int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
774				int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha);
775				ori_scan += 2;
776				*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
777 				dest_scan ++;
778				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
779 				dest_scan ++;
780				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
781				dest_scan += 2;
782			}
783		}
784#endif
785	}
786	/*-----------------------------------------------------------------------------------------------------*/
787	void CFX_SkiaRenderer::CompositeSpanRGB24_2(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
788			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
789			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
790			FX_LPBYTE dest_extra_alpha_scan)
791	{
792		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left + (span_left<<1);
793		int col_start = span_left < clip_left ? clip_left - span_left : 0;
794		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
795		if (col_end < col_start) return; // do nothing.
796		dest_scan += (col_start<<1)+col_start;
797		int src_alpha;
798#if 0
799		if (m_bFullCover)
800			src_alpha = m_Alpha;
801		else
802#endif
803			src_alpha = m_Alpha * cover_scan / 255;
804		if (src_alpha == 255) {
805			for (int col = col_start; col < col_end; col ++) {
806				*dest_scan++ = m_Blue;
807				*dest_scan++ = m_Green;
808				*dest_scan++ = m_Red;
809			}
810			return;
811		}
812		for (int col = col_start; col < col_end; col ++) {
813			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
814			dest_scan ++;
815			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
816			dest_scan ++;
817			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
818			dest_scan ++;
819		}
820	}
821	void CFX_SkiaRenderer::CompositeSpanRGB24_3(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
822			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
823			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
824			FX_LPBYTE dest_extra_alpha_scan)
825	{
826		ASSERT(!m_pDevice->IsCmykImage());
827		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left + (span_left<<1);
828		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + span_left + (span_left<<1);
829		int col_start = span_left < clip_left ? clip_left - span_left : 0;
830		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
831		if (col_end < col_start) return; // do nothing.
832		dest_scan += (col_start<<1) + col_start;
833		ori_scan += (col_start<<1) + col_start;
834		if (m_Alpha == 255&&cover_scan == 255) {
835			for (int col = col_start; col < col_end; col ++) {
836				*dest_scan ++ = m_Blue;
837 				*dest_scan ++ = m_Green;
838				*dest_scan ++ = m_Red;
839			}
840			return;
841		}
842		for (int col = col_start; col < col_end; col ++) {
843#if 0
844			if (m_bFullCover) {
845				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, m_Alpha);
846				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, m_Alpha);
847				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, m_Alpha);
848				continue;
849			}
850#endif
851			int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, m_Alpha);
852			int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, m_Alpha);
853			int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, m_Alpha);
854			*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
855 			dest_scan ++;
856			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
857 			dest_scan ++;
858			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
859			dest_scan ++;
860		}
861	}
862	void CFX_SkiaRenderer::CompositeSpanRGB24_6(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
863			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
864			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
865			FX_LPBYTE dest_extra_alpha_scan)
866	{
867		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left+(span_left<<1);
868		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
869		int col_start = span_left < clip_left ? clip_left - span_left : 0;
870		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
871		if (col_end < col_start) return; // do nothing.
872		dest_scan += col_start + (col_start << 1);
873#if 1
874		int src_alpha = m_Alpha * cover_scan /255;
875		for (int col = col_start; col < col_end; col ++) {
876			int src_alpha1 = src_alpha * clip_scan[col] / 255;
877			if (!src_alpha1) {
878				dest_scan += 3;
879				continue;
880			}
881			if (src_alpha1 == 255) {
882				*dest_scan++ = m_Blue;
883				*dest_scan++ = m_Green;
884				*dest_scan++ = m_Red;
885			} else {
886				// Dest format: Rgb
887				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha1);
888				dest_scan ++;
889				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha1);
890				dest_scan ++;
891				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha1);
892				dest_scan ++;
893			}
894		}
895#else
896		if (m_bFullCover) {
897			for (int col = col_start; col < col_end; col ++) {
898				int src_alpha = m_Alpha * clip_scan[col] / 255;
899				if (!src_alpha) {
900					dest_scan += 3;
901					continue;
902				}
903				if (src_alpha == 255) {
904					*dest_scan++ = m_Blue;
905					*dest_scan++ = m_Green;
906					*dest_scan++ = m_Red;
907				} else {
908					// Dest format: Rgb
909					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
910					dest_scan ++;
911					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
912					dest_scan ++;
913					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
914					dest_scan ++;
915				}
916			}
917		} else {
918			int src_alpha = m_Alpha * cover_scan /255;
919			for (int col = col_start; col < col_end; col ++) {
920				int src_alpha1 = src_alpha * clip_scan[col] / 255;
921				if (!src_alpha1) {
922					dest_scan += 3;
923					continue;
924				}
925				if (src_alpha1 == 255) {
926					*dest_scan++ = m_Blue;
927					*dest_scan++ = m_Green;
928					*dest_scan++ = m_Red;
929				} else {
930					// Dest format: Rgb
931					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha1);
932					dest_scan ++;
933					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha1);
934					dest_scan ++;
935					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha1);
936					dest_scan ++;
937				}
938			}
939		}
940#endif
941	}
942	void CFX_SkiaRenderer::CompositeSpanRGB24_7(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
943			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
944			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
945			FX_LPBYTE dest_extra_alpha_scan)
946	{
947		ASSERT(!m_pDevice->IsCmykImage());
948		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left+(span_left<<1);
949		ori_scan  = (FX_BYTE*)m_pOriDevice->GetScanline(span_top) + span_left+(span_left<<1);
950		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
951		int col_start = span_left < clip_left ? clip_left - span_left : 0;
952		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
953		if (col_end < col_start) return; // do nothing.
954		dest_scan += col_start + (col_start<<1);
955		ori_scan += col_start + (col_start<<1);
956#if 1
957		for (int col = col_start; col < col_end; col ++) {
958			int src_alpha = m_Alpha * clip_scan[col] / 255;
959			if (src_alpha == 255 && cover_scan == 255) {
960				*dest_scan++ = m_Blue;
961				*dest_scan++ = m_Green;
962				*dest_scan++ = m_Red;
963				ori_scan += 3;
964				continue;
965			}
966			int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
967			int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
968			int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
969			*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
970 			dest_scan ++;
971			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
972 			dest_scan ++;
973			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
974			dest_scan ++;
975		}
976#else
977		if (m_bFullCover) {
978			for (int col = col_start; col < col_end; col ++) {
979				int src_alpha = m_Alpha * clip_scan[col] / 255;
980				if (!src_alpha){
981					*dest_scan++ = *ori_scan++;
982					*dest_scan++ = *ori_scan++;
983					*dest_scan++ = *ori_scan++;
984					continue;
985				}
986				if (src_alpha == 255){
987					*dest_scan++ = m_Blue;
988					*dest_scan++ = m_Green;
989					*dest_scan++ = m_Red;
990					ori_scan += 3;
991					continue;
992				}
993				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
994				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
995				*dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
996			}
997		} else {
998			for (int col = col_start; col < col_end; col ++) {
999				int src_alpha = m_Alpha * clip_scan[col] / 255;
1000				if (src_alpha == 255 && cover_scan == 255) {
1001					*dest_scan++ = m_Blue;
1002					*dest_scan++ = m_Green;
1003					*dest_scan++ = m_Red;
1004					ori_scan += 3;
1005					continue;
1006				}
1007				int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha);
1008				int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha);
1009				int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha);
1010				*dest_scan = FXDIB_ALPHA_MERGE( *dest_scan, b, cover_scan);
1011 				dest_scan ++;
1012				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan);
1013 				dest_scan ++;
1014				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan);
1015				dest_scan ++;
1016			}
1017		}
1018#endif
1019	}
1020	void CFX_SkiaRenderer::CompositeSpanRGB24_10(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
1021			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
1022			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
1023			FX_LPBYTE dest_extra_alpha_scan)
1024	{
1025		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left+(span_left<<1);
1026		dest_extra_alpha_scan =  (FX_BYTE*)m_pDevice->m_pAlphaMask->GetScanline(span_top)+span_left;
1027		int col_start = span_left < clip_left ? clip_left - span_left : 0;
1028		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
1029		if (col_end < col_start) return; // do nothing.
1030		dest_scan += col_start+(col_start<<1);
1031#if 1
1032		if (m_Alpha == 255 && cover_scan == 255) {
1033			for (int col = col_start; col < col_end; col ++) {
1034				*dest_scan++ = (FX_BYTE)m_Blue;
1035				*dest_scan++ = (FX_BYTE)m_Green;
1036				*dest_scan++ = (FX_BYTE)m_Red;
1037				*dest_extra_alpha_scan++ = 255;
1038			}
1039			return;
1040		}
1041		int src_alpha = m_Alpha * cover_scan / 255;
1042		for (int col = col_start; col < col_end; col ++) {
1043			// Dest format: Rgba
1044			// calculate destination alpha (it's union of source and dest alpha)
1045			FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1046								(*dest_extra_alpha_scan) * src_alpha / 255;
1047			*dest_extra_alpha_scan++ = dest_alpha;
1048			int alpha_ratio = src_alpha*255/dest_alpha;
1049			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1050			dest_scan ++;
1051			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1052			dest_scan ++;
1053			*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1054			dest_scan ++;
1055		}
1056#else
1057		if (m_bFullCover) {
1058			if (m_Alpha == 255) {
1059				for (int col = col_start; col < col_end; col ++) {
1060					*dest_scan++ = (FX_BYTE)m_Blue;
1061					*dest_scan++ = (FX_BYTE)m_Green;
1062					*dest_scan++ = (FX_BYTE)m_Red;
1063					*dest_extra_alpha_scan++ = 255;
1064				}
1065				return;
1066			}
1067			for (int col = col_start; col < col_end; col ++) {
1068				// Dest format: Rgba
1069				// calculate destination alpha (it's union of source and dest alpha)
1070				FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + m_Alpha -
1071									(*dest_extra_alpha_scan) * m_Alpha / 255;
1072				*dest_extra_alpha_scan++ = dest_alpha;
1073				int alpha_ratio = m_Alpha*255/dest_alpha;
1074				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1075				dest_scan ++;
1076				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1077				dest_scan ++;
1078				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1079				dest_scan ++;
1080			}
1081		} else {
1082			if (m_Alpha == 255 && cover_scan == 255) {
1083				for (int col = col_start; col < col_end; col ++) {
1084					*dest_scan++ = (FX_BYTE)m_Blue;
1085					*dest_scan++ = (FX_BYTE)m_Green;
1086					*dest_scan++ = (FX_BYTE)m_Red;
1087					*dest_extra_alpha_scan++ = 255;
1088				}
1089				return;
1090			}
1091			int src_alpha = m_Alpha * cover_scan / 255;
1092			for (int col = col_start; col < col_end; col ++) {
1093				// Dest format: Rgba
1094				// calculate destination alpha (it's union of source and dest alpha)
1095				FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1096									(*dest_extra_alpha_scan) * src_alpha / 255;
1097				*dest_extra_alpha_scan++ = dest_alpha;
1098				int alpha_ratio = src_alpha*255/dest_alpha;
1099				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1100				dest_scan ++;
1101				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1102				dest_scan ++;
1103				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1104				dest_scan ++;
1105			}
1106		}
1107#endif
1108	}
1109	void CFX_SkiaRenderer::CompositeSpanRGB24_14(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
1110			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
1111			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
1112			FX_LPBYTE dest_extra_alpha_scan)
1113	{
1114		dest_scan = (FX_BYTE*)m_pDevice->GetScanline(span_top) + span_left+(span_left<<1);
1115		dest_extra_alpha_scan =  (FX_BYTE*)m_pDevice->m_pAlphaMask->GetScanline(span_top)+span_left;
1116		clip_scan = (FX_BYTE*)m_pClipMask->GetScanline(span_top-clip_top) - clip_left + span_left;
1117		int col_start = span_left < clip_left ? clip_left - span_left : 0;
1118		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
1119		if (col_end < col_start) return; // do nothing.
1120		dest_scan += col_start + (col_start << 1);
1121#if 1
1122		int src_alpha = m_Alpha * cover_scan / 255;
1123		for (int col = col_start; col < col_end; col ++) {
1124			int src_alpha1 = src_alpha * clip_scan[col] / 255;
1125			if (!src_alpha1) {
1126				dest_extra_alpha_scan++;
1127				dest_scan += 3;
1128				continue;
1129			}
1130			if (src_alpha1 == 255) {
1131				*dest_scan++ = (FX_BYTE)m_Blue;
1132				*dest_scan++ = (FX_BYTE)m_Green;
1133				*dest_scan++ = (FX_BYTE)m_Red;
1134				*dest_extra_alpha_scan++ = (FX_BYTE)m_Alpha;
1135			} else {
1136				// Dest format: Rgba
1137				// calculate destination alpha (it's union of source and dest alpha)
1138				FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha1 -
1139									(*dest_extra_alpha_scan) * src_alpha1 / 255;
1140				*dest_extra_alpha_scan++ = dest_alpha;
1141				int alpha_ratio = src_alpha1*255/dest_alpha;
1142				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1143				dest_scan ++;
1144				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1145				dest_scan ++;
1146				*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1147				dest_scan ++;
1148			}
1149		}
1150#else
1151		if (m_bFullCover) {
1152			for (int col = col_start; col < col_end; col ++) {
1153				int src_alpha = m_Alpha * clip_scan[col] / 255;
1154				if (!src_alpha) {
1155					dest_extra_alpha_scan++;
1156					dest_scan += 3;
1157					continue;
1158				}
1159				if (src_alpha == 255) {
1160					*dest_scan++ = (FX_BYTE)m_Blue;
1161					*dest_scan++ = (FX_BYTE)m_Green;
1162					*dest_scan++ = (FX_BYTE)m_Red;
1163					*dest_extra_alpha_scan++ = (FX_BYTE)m_Alpha;
1164				} else {
1165					// Dest format: Rgba
1166					// calculate destination alpha (it's union of source and dest alpha)
1167					FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1168										(*dest_extra_alpha_scan) * src_alpha / 255;
1169					*dest_extra_alpha_scan++ = dest_alpha;
1170					int alpha_ratio = src_alpha*255/dest_alpha;
1171					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1172					dest_scan ++;
1173					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1174					dest_scan ++;
1175					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1176					dest_scan ++;
1177				}
1178			}
1179		} else {
1180			int src_alpha = m_Alpha * cover_scan / 255;
1181			for (int col = col_start; col < col_end; col ++) {
1182				int src_alpha1 = m_Alpha * cover_scan * clip_scan[col] / 255;
1183				if (!src_alpha1) {
1184					dest_extra_alpha_scan++;
1185					dest_scan += 3;
1186					continue;
1187				}
1188				if (src_alpha1 == 255) {
1189					*dest_scan++ = (FX_BYTE)m_Blue;
1190					*dest_scan++ = (FX_BYTE)m_Green;
1191					*dest_scan++ = (FX_BYTE)m_Red;
1192					*dest_extra_alpha_scan++ = (FX_BYTE)m_Alpha;
1193				} else {
1194					// Dest format: Rgba
1195					// calculate destination alpha (it's union of source and dest alpha)
1196					FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha1 -
1197										(*dest_extra_alpha_scan) * src_alpha1 / 255;
1198					*dest_extra_alpha_scan++ = dest_alpha;
1199					int alpha_ratio = src_alpha1*255/dest_alpha;
1200					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1201					dest_scan ++;
1202					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1203					dest_scan ++;
1204					*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1205					dest_scan ++;
1206				}
1207			}
1208		}
1209#endif
1210	}
1211	/*-----------------------------------------------------------------------------------------------------*/
1212
1213	// A general alpha merge function (with clipping mask). Cmyka/Cmyk device.
1214	void CFX_SkiaRenderer::CompositeSpanCMYK(FX_LPBYTE dest_scan, FX_LPBYTE ori_scan,int Bpp,
1215			int span_left, int span_len, int span_top, FX_BYTE cover_scan,
1216			int clip_top, int clip_left, int clip_right, FX_LPBYTE clip_scan,
1217			FX_LPBYTE dest_extra_alpha_scan)
1218	{
1219		ASSERT(!m_bRgbByteOrder);
1220		// Cmyk(a)
1221		int col_start = span_left < clip_left ? clip_left - span_left : 0;
1222		int col_end = (span_left + span_len) < clip_right ? span_len : (clip_right - span_left);
1223		if (col_end < col_start) return; // do nothing.
1224		dest_scan += col_start * 4;
1225		Bpp; // for avoid compile warning.
1226
1227		if (dest_extra_alpha_scan) {
1228			// CMYKa
1229			for (int col = col_start; col < col_end; col ++) {
1230				int src_alpha;
1231				if (m_bFullCover) {
1232					if (clip_scan)
1233						src_alpha = m_Alpha * clip_scan[col] / 255;
1234					else
1235						src_alpha = m_Alpha;
1236				} else {
1237					if (clip_scan)
1238						src_alpha = m_Alpha * cover_scan * clip_scan[col] / 255 / 255;
1239					else
1240						src_alpha = m_Alpha * cover_scan / 255;
1241				}
1242
1243				if (src_alpha) {
1244					if (src_alpha == 255) {
1245						*(FX_CMYK*)dest_scan = m_Color;
1246						*dest_extra_alpha_scan = (FX_BYTE)m_Alpha;
1247					} else {
1248						// Dest format: Cmyka
1249						// calculate destination alpha (it's union of source and dest alpha)
1250						FX_BYTE dest_alpha = (*dest_extra_alpha_scan) + src_alpha -
1251							(*dest_extra_alpha_scan) * src_alpha / 255;
1252						*dest_extra_alpha_scan++ = dest_alpha;
1253						int alpha_ratio = src_alpha*255/dest_alpha;
1254						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
1255						dest_scan ++;
1256						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
1257						dest_scan ++;
1258						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
1259						dest_scan ++;
1260						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio);
1261						dest_scan ++;
1262						continue;
1263					}
1264				}
1265				dest_extra_alpha_scan++;
1266				dest_scan += 4;
1267			}
1268		} else {
1269			// CMYK
1270			for (int col = col_start; col < col_end; col ++) {
1271				int src_alpha;
1272				if (clip_scan)
1273					src_alpha = m_Alpha * cover_scan * clip_scan[col] / 255 / 255;
1274				else
1275					src_alpha = m_Alpha * cover_scan / 255;
1276
1277				if (src_alpha) {
1278					if (src_alpha == 255) {
1279						*(FX_CMYK*)dest_scan = m_Color;
1280					} else {
1281						// Dest format: cmyk
1282						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
1283						dest_scan ++;
1284						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
1285						dest_scan ++;
1286						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
1287						dest_scan ++;
1288						*dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
1289						dest_scan ++;
1290						continue;
1291					}
1292				}
1293				dest_scan += 4;
1294			}
1295		}
1296	}
1297
1298
1299
1300	//--------------------------------------------------------------------
1301	FX_BOOL CFX_SkiaRenderer::Init(CFX_DIBitmap* pDevice, CFX_DIBitmap* pOriDevice, const CFX_ClipRgn* pClipRgn, FX_DWORD color, FX_BOOL bFullCover, FX_BOOL bRgbByteOrder,
1302		int alpha_flag, void* pIccTransform) //The alpha flag must be fill_flag if exist.
1303	{
1304		m_pDevice = pDevice;
1305		m_pClipRgn = pClipRgn;
1306		m_bRgbByteOrder = bRgbByteOrder;
1307		m_pOriDevice = pOriDevice;
1308		m_pDestScan = NULL;
1309		m_pDestExtraAlphaScan = NULL;
1310		m_pOriScan = NULL;
1311		m_pClipScan = NULL;
1312		composite_span = NULL;
1313		if (m_pClipRgn)
1314			m_ClipBox = m_pClipRgn->GetBox();
1315		else {
1316			m_ClipBox.left = m_ClipBox.top = 0;
1317			m_ClipBox.right = m_pDevice->GetWidth();
1318			m_ClipBox.bottom = m_pDevice->GetHeight();
1319		}
1320		m_pClipMask = NULL;
1321		if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF)
1322		{
1323			m_pClipMask = m_pClipRgn->GetMask();
1324			m_pClipScan = m_pClipMask->GetBuffer();
1325		}
1326		if (m_pDevice->m_pAlphaMask)
1327			m_pDestExtraAlphaScan = m_pDevice->m_pAlphaMask->GetBuffer();
1328		if (m_pOriDevice)
1329			m_pOriScan = m_pOriDevice->GetBuffer();
1330		m_pDestScan = m_pDevice->GetBuffer();
1331
1332		m_bFullCover = bFullCover;
1333
1334		FX_BOOL bObjectCMYK = FXGETFLAG_COLORTYPE(alpha_flag);
1335		FX_BOOL bDeviceCMYK = pDevice->IsCmykImage();
1336
1337		m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color);
1338
1339		ICodec_IccModule* pIccModule = NULL;
1340		// No lcms engine, we skip the transform
1341		if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule())
1342			pIccTransform = NULL;
1343		else
1344			pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
1345
1346		if (m_pDevice->GetBPP() == 8) { // Gray(a) device
1347			ASSERT(!m_bRgbByteOrder);
1348			if (m_pDevice->IsAlphaMask()) {
1349				//Alpha Mask
1350				m_Gray = 255;
1351			} else {
1352				//Gray(a) device
1353				if (pIccTransform) {
1354					FX_BYTE gray;
1355					color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1356					pIccModule->TranslateScanline(pIccTransform, &gray, (FX_LPCBYTE)&color, 1);
1357					m_Gray = gray;
1358				} else {
1359					if (bObjectCMYK) {
1360						FX_BYTE r, g, b;
1361						AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
1362							r, g, b);
1363						m_Gray = FXRGB2GRAY(r, g, b);
1364					} else {
1365						m_Gray = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
1366					}
1367				}
1368			}
1369		} else {
1370			if (bDeviceCMYK) { // Cmyk(a) Device
1371				ASSERT(!m_bRgbByteOrder);
1372				//TODO... opt for cmyk
1373				composite_span = &CFX_SkiaRenderer::CompositeSpanCMYK;
1374				if (bObjectCMYK) {
1375					m_Color = FXCMYK_TODIB(color);
1376					if (pIccTransform)
1377						pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&m_Color, 1);
1378				} else { // Object RGB
1379					if (!pIccTransform)
1380						return FALSE;
1381					color = FXARGB_TODIB(color);
1382					pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&color, 1);
1383				}
1384				m_Red	= ((FX_LPBYTE)&m_Color)[0];
1385				m_Green = ((FX_LPBYTE)&m_Color)[1];
1386				m_Blue	= ((FX_LPBYTE)&m_Color)[2];
1387				m_Gray	= ((FX_LPBYTE)&m_Color)[3];
1388				return TRUE;
1389			} else {
1390				if (pIccTransform) {
1391					color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
1392					pIccModule->TranslateScanline(pIccTransform, (FX_LPBYTE)&m_Color, (FX_LPCBYTE)&color, 1);
1393					((FX_LPBYTE)&m_Color)[3] = m_Alpha;
1394					m_Red = ((FX_LPBYTE)&m_Color)[2];
1395					m_Green = ((FX_LPBYTE)&m_Color)[1];
1396					m_Blue = ((FX_LPBYTE)&m_Color)[0];
1397					// Need Johnson to improvement it.
1398					if (m_bRgbByteOrder) {
1399						// swap
1400						m_Red = ((FX_LPBYTE)&m_Color)[0];
1401						m_Blue = ((FX_LPBYTE)&m_Color)[2];
1402						m_Color = FXARGB_TODIB(m_Color);
1403						m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1404					}
1405				} else {
1406					if (bObjectCMYK) {
1407						FX_BYTE r, g, b;
1408						AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),
1409							r, g, b);
1410						m_Color = FXARGB_MAKE(m_Alpha, r, g, b);
1411						if (m_bRgbByteOrder){
1412							m_Color = FXARGB_TOBGRORDERDIB(m_Color);
1413							m_Red = b; m_Green = g; m_Blue = r;//
1414						}else {
1415							m_Color = FXARGB_TODIB(m_Color);
1416							m_Red = r; m_Green = g; m_Blue = b;//
1417						}
1418					} else {
1419						if (m_bRgbByteOrder){
1420							m_Color = FXARGB_TOBGRORDERDIB(color);
1421							ArgbDecode(color, m_Alpha, m_Blue, m_Green, m_Red); //
1422						}else {
1423							m_Color = FXARGB_TODIB(color);
1424							ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue);
1425						}
1426					}
1427				}
1428			}
1429		}
1430		// Get palette transparency selector
1431		m_ProcessFilter = (m_pOriDevice? 1 : 0)	/* has Ori Device flag */
1432						+ (m_pDevice->GetBPP() >= 8 ? 2 : 0)	/* bpp flag */
1433						+ (m_pClipMask? 4 : 0)					/* has clip region flag */
1434						+ (m_pDevice->m_pAlphaMask? 8 : 0);		/* has Alpha Mask chanel flag */
1435		switch(m_ProcessFilter) {
1436			case 0:
1437				composite_span = &CFX_SkiaRenderer::CompositeSpan1bpp_0;
1438				break;
1439			case 2:
1440				{
1441					if (m_pDevice->GetBPP() == 8)
1442						composite_span = &CFX_SkiaRenderer::CompositeSpanGray_2;
1443					else if (m_pDevice->GetBPP() == 24)
1444						composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_2;
1445					else
1446						composite_span = m_pDevice->HasAlpha()?&CFX_SkiaRenderer::CompositeSpanARGB_2 : &CFX_SkiaRenderer::CompositeSpanRGB32_2;
1447				}
1448				break;
1449			case 3:
1450				{
1451					if (m_pDevice->GetBPP() == 8)
1452						composite_span = &CFX_SkiaRenderer::CompositeSpanGray_3;
1453					else if (m_pDevice->GetBPP() == 24)
1454						composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_3;
1455					else
1456						composite_span = m_pDevice->HasAlpha()?&CFX_SkiaRenderer::CompositeSpanARGB_3 : &CFX_SkiaRenderer::CompositeSpanRGB32_3;
1457				}
1458				break;
1459			case 4:
1460				composite_span = &CFX_SkiaRenderer::CompositeSpan1bpp_4;
1461				break;
1462			case 6:
1463				{
1464					if (m_pDevice->GetBPP() == 8)
1465						composite_span = &CFX_SkiaRenderer::CompositeSpanGray_6;
1466					else if (m_pDevice->GetBPP() == 24)
1467						composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_6;
1468					else
1469						composite_span = m_pDevice->HasAlpha()?&CFX_SkiaRenderer::CompositeSpanARGB_6 : &CFX_SkiaRenderer::CompositeSpanRGB32_6;
1470				}
1471				break;
1472			case 7:
1473				{
1474					if (m_pDevice->GetBPP() == 8)
1475						composite_span = &CFX_SkiaRenderer::CompositeSpanGray_7;
1476					else if (m_pDevice->GetBPP() == 24)
1477						composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_7;
1478					else
1479						composite_span = m_pDevice->HasAlpha()?&CFX_SkiaRenderer::CompositeSpanARGB_7 : &CFX_SkiaRenderer::CompositeSpanRGB32_7;
1480				}
1481				break;
1482			case 1:
1483			case 5:
1484			case 8:
1485			case 9:
1486			case 11:
1487			case 12:
1488			case 13:
1489			case 15:
1490				//TODO...
1491				break;
1492			case 10:
1493				composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_10;
1494				break;
1495			case 14:
1496				composite_span = &CFX_SkiaRenderer::CompositeSpanRGB24_14;
1497				break;
1498		}
1499		if (composite_span == NULL)
1500			return FALSE;
1501		return TRUE;
1502	}
1503
1504	/*----------------------------------------------------------------------------------------------------*/
1505	void CFX_SkiaA8Renderer::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[])
1506	{
1507		FXSYS_assert(m_pDevice);
1508		int dst_y = y - m_Top;
1509		if (dst_y < 0 || dst_y >=  m_pDevice->GetHeight())
1510			return;
1511
1512		FX_LPBYTE dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * dst_y;
1513		FX_LPBYTE dest_pos = dest_scan;
1514		while (1)
1515		{
1516			if (x >= m_dstWidth)
1517				return;
1518			int width = runs[0];
1519			SkASSERT(width >= 0);
1520			if (width <= 0)
1521				return;
1522			unsigned aa = antialias[0];
1523			if (aa) {
1524				int col_start = x < m_Left ? 0 : x - m_Left;
1525				int col_end = x + width;
1526				col_end = col_end < m_dstWidth ? col_end - m_Left: m_pDevice->GetWidth();
1527				int result = col_end - col_start;
1528				if (result > 0) {
1529					dest_pos = dest_scan + col_start;
1530					if (result >= 4)
1531						FXSYS_memset32(dest_pos, FXARGB_MAKE(aa, aa, aa, aa),result);
1532					else
1533						FXSYS_memset(dest_pos,aa,result);
1534				}
1535			}
1536			runs += width;
1537			antialias += width;
1538			x += width;
1539		}
1540	}
1541	void CFX_SkiaA8Renderer::blitH(int x, int y, int width)
1542	{
1543		FXSYS_assert(m_pDevice);
1544		int dst_y = y - m_Top;
1545		if (dst_y < 0 || dst_y >=  m_pDevice->GetHeight())
1546			return;
1547		if (x >= m_dstWidth)
1548			return;
1549		FX_LPBYTE dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * dst_y;
1550		int col_start = x < m_Left ? 0 : x - m_Left;
1551		int col_end = x + width;
1552		col_end = col_end < m_dstWidth ? col_end - m_Left: m_pDevice->GetWidth();
1553		int result = col_end - col_start;
1554		if (result > 0) {
1555			FX_BYTE* dest_pos = dest_scan + col_start;
1556			if (result >= 4)
1557				FXSYS_memset32(dest_pos, 0xffffffff,result);
1558			else
1559				FXSYS_memset(dest_pos,255,result);
1560		}
1561	}
1562	void CFX_SkiaA8Renderer::blitV(int x, int y, int height, SkAlpha alpha)
1563	{
1564		FXSYS_assert(alpha);
1565		if (alpha == 255) {
1566			this->blitRect(x, y, 1, height);
1567		} else {
1568			int16_t runs[2];
1569			runs[0] = 1;
1570			runs[1] = 0;
1571			while (--height >= 0) {
1572				if (y >= m_dstHeight)
1573					return;
1574				this->blitAntiH(x, y ++, &alpha, runs);
1575			}
1576		}
1577	}
1578	void CFX_SkiaA8Renderer::blitRect(int x, int y, int width, int height)
1579	{
1580		FXSYS_assert(m_pDevice);
1581		while (--height >= 0) {
1582			if (y >= m_dstHeight)
1583				return;
1584			blitH(x , y ++, width);
1585		}
1586	}
1587
1588	void CFX_SkiaA8Renderer::blitAntiRect(int x, int y, int width, int height,
1589                             SkAlpha leftAlpha, SkAlpha rightAlpha)
1590	{
1591		blitV(x++, y, height, leftAlpha);
1592		if (width > 0) {
1593			blitRect(x, y, width, height);
1594			x += width;
1595		}
1596		blitV(x, y, height, rightAlpha);
1597	}
1598
1599	FX_BOOL CFX_SkiaA8Renderer::Init(CFX_DIBitmap* pDevice, int Left, int Top)
1600	{
1601		m_pDevice = pDevice;
1602		m_Left = Left;
1603		m_Top = Top;
1604		if (pDevice){
1605			m_dstWidth = m_Left + pDevice->GetWidth();
1606			m_dstHeight = m_Top + pDevice->GetHeight();
1607		}
1608		return TRUE;
1609	}
1610#endif
1611