Initial commit.
[pdfium.git] / core / src / fxge / dib / fx_dib_main.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4  \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "../../../include/fxge/fx_dib.h"\r
8 #include "../../../include/fxge/fx_ge.h"\r
9 #include "../../../include/fxcodec/fx_codec.h"\r
10 #include "dib_int.h"\r
11 #include <limits.h>\r
12 FX_BOOL ConvertBuffer(FXDIB_Format dest_format, FX_LPBYTE dest_buf, int dest_pitch, int width, int height,\r
13                       const CFX_DIBSource* pSrcBitmap, int src_left, int src_top, FX_DWORD*& pal, void* pIccTransform);\r
14 void CmykDecode(FX_DWORD cmyk, int& c, int& m, int& y, int& k)\r
15 {\r
16     c = FXSYS_GetCValue(cmyk);\r
17     m = FXSYS_GetMValue(cmyk);\r
18     y = FXSYS_GetYValue(cmyk);\r
19     k = FXSYS_GetKValue(cmyk);\r
20 }\r
21 void ArgbDecode(FX_DWORD argb, int& a, int& r, int& g, int& b)\r
22 {\r
23     a = FXARGB_A(argb);\r
24     r = FXARGB_R(argb);\r
25     g = FXARGB_G(argb);\r
26     b = FXARGB_B(argb);\r
27 }\r
28 void ArgbDecode(FX_DWORD argb, int& a, FX_COLORREF& rgb)\r
29 {\r
30     a = FXARGB_A(argb);\r
31     rgb = FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));\r
32 }\r
33 FX_DWORD ArgbEncode(int a, FX_COLORREF rgb)\r
34 {\r
35     return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb), FXSYS_GetBValue(rgb));\r
36 }\r
37 CFX_DIBSource::CFX_DIBSource()\r
38 {\r
39     m_bpp = 0;\r
40     m_AlphaFlag = 0;\r
41     m_Width = m_Height = 0;\r
42     m_Pitch = 0;\r
43     m_pPalette = NULL;\r
44     m_pAlphaMask = NULL;\r
45 }\r
46 CFX_DIBSource::~CFX_DIBSource()\r
47 {\r
48     if (m_pPalette) {\r
49         FX_Free(m_pPalette);\r
50     }\r
51     if (m_pAlphaMask) {\r
52         delete m_pAlphaMask;\r
53     }\r
54 }\r
55 CFX_DIBitmap::CFX_DIBitmap()\r
56 {\r
57     m_bExtBuf = FALSE;\r
58     m_pBuffer = NULL;\r
59     m_pPalette = NULL;\r
60 }\r
61 #define _MAX_OOM_LIMIT_ 12000000\r
62 FX_BOOL CFX_DIBitmap::Create(int width, int height, FXDIB_Format format, FX_LPBYTE pBuffer, int pitch)\r
63 {\r
64     m_pBuffer = NULL;\r
65     m_bpp = (FX_BYTE)format;\r
66     m_AlphaFlag = (FX_BYTE)(format >> 8);\r
67     m_Width = m_Height = m_Pitch = 0;\r
68     if (width <= 0 || height <= 0 || pitch < 0) {\r
69         return FALSE;\r
70     }\r
71     if ((INT_MAX - 31) / width < (format & 0xff)) {\r
72         return FALSE;\r
73     }\r
74     if (!pitch) {\r
75         pitch = (width * (format & 0xff) + 31) / 32 * 4;\r
76     }\r
77     if ((1 << 30) / pitch < height) {\r
78         return FALSE;\r
79     }\r
80     if (pBuffer) {\r
81         m_pBuffer = pBuffer;\r
82         m_bExtBuf = TRUE;\r
83     } else {\r
84         int size = pitch * height + 4;\r
85         int oomlimit = _MAX_OOM_LIMIT_;\r
86         if (oomlimit >= 0 && size >= oomlimit) {\r
87             m_pBuffer = FX_AllocNL(FX_BYTE, size);\r
88         } else {\r
89             m_pBuffer = FX_Alloc(FX_BYTE, size);\r
90         }\r
91         if (m_pBuffer == NULL) {\r
92             return FALSE;\r
93         }\r
94         FXSYS_memset32(m_pBuffer, 0, sizeof (FX_BYTE) * size);\r
95     }\r
96     m_Width = width;\r
97     m_Height = height;\r
98     m_Pitch = pitch;\r
99     if (HasAlpha() && format != FXDIB_Argb) {\r
100         FX_BOOL ret = TRUE;\r
101         ret = BuildAlphaMask();\r
102         if (!ret) {\r
103             if (!m_bExtBuf && m_pBuffer) {\r
104                 FX_Free(m_pBuffer);\r
105                 m_pBuffer = NULL;\r
106                 m_Width = m_Height = m_Pitch = 0;\r
107                 return FALSE;\r
108             }\r
109         }\r
110     }\r
111     return TRUE;\r
112 }\r
113 FX_BOOL CFX_DIBitmap::Copy(const CFX_DIBSource* pSrc)\r
114 {\r
115     if (m_pBuffer) {\r
116         return FALSE;\r
117     }\r
118     if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat())) {\r
119         return FALSE;\r
120     }\r
121     CopyPalette(pSrc->GetPalette());\r
122     CopyAlphaMask(pSrc->m_pAlphaMask);\r
123     for (int row = 0; row < pSrc->GetHeight(); row ++) {\r
124         FXSYS_memcpy32(m_pBuffer + row * m_Pitch, pSrc->GetScanline(row), m_Pitch);\r
125     }\r
126     return TRUE;\r
127 }\r
128 CFX_DIBitmap::~CFX_DIBitmap()\r
129 {\r
130     if (m_pBuffer && !m_bExtBuf) {\r
131         FX_Free(m_pBuffer);\r
132     }\r
133     m_pBuffer = NULL;\r
134 }\r
135 void CFX_DIBitmap::TakeOver(CFX_DIBitmap* pSrcBitmap)\r
136 {\r
137     if (m_pBuffer && !m_bExtBuf) {\r
138         FX_Free(m_pBuffer);\r
139     }\r
140     if (m_pPalette) {\r
141         FX_Free(m_pPalette);\r
142     }\r
143     if (m_pAlphaMask) {\r
144         delete m_pAlphaMask;\r
145     }\r
146     m_pBuffer = pSrcBitmap->m_pBuffer;\r
147     m_pPalette = pSrcBitmap->m_pPalette;\r
148     m_pAlphaMask = pSrcBitmap->m_pAlphaMask;\r
149     pSrcBitmap->m_pBuffer = NULL;\r
150     pSrcBitmap->m_pPalette = NULL;\r
151     pSrcBitmap->m_pAlphaMask = NULL;\r
152     m_bpp = pSrcBitmap->m_bpp;\r
153     m_bExtBuf = pSrcBitmap->m_bExtBuf;\r
154     m_AlphaFlag = pSrcBitmap->m_AlphaFlag;\r
155     m_Width = pSrcBitmap->m_Width;\r
156     m_Height = pSrcBitmap->m_Height;\r
157     m_Pitch = pSrcBitmap->m_Pitch;\r
158 }\r
159 CFX_DIBitmap* CFX_DIBSource::Clone(const FX_RECT* pClip) const\r
160 {\r
161     FX_RECT rect(0, 0, m_Width, m_Height);\r
162     if (pClip) {\r
163         rect.Intersect(*pClip);\r
164         if (rect.IsEmpty()) {\r
165             return NULL;\r
166         }\r
167     }\r
168     CFX_DIBitmap* pNewBitmap = FX_NEW CFX_DIBitmap;\r
169     if (!pNewBitmap) {\r
170         return NULL;\r
171     }\r
172     if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat())) {\r
173         delete pNewBitmap;\r
174         return NULL;\r
175     }\r
176     pNewBitmap->CopyPalette(m_pPalette);\r
177     pNewBitmap->CopyAlphaMask(m_pAlphaMask, pClip);\r
178     if (GetBPP() == 1 && rect.left % 8 != 0) {\r
179         int left_shift = rect.left % 32;\r
180         int right_shift = 32 - left_shift;\r
181         int dword_count = pNewBitmap->m_Pitch / 4;\r
182         for (int row = rect.top; row < rect.bottom; row ++) {\r
183             FX_DWORD* src_scan = (FX_DWORD*)GetScanline(row) + rect.left / 32;\r
184             FX_DWORD* dest_scan = (FX_DWORD*)pNewBitmap->GetScanline(row - rect.top);\r
185             for (int i = 0; i < dword_count; i ++) {\r
186                 dest_scan[i] = (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);\r
187             }\r
188         }\r
189     } else {\r
190         int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;\r
191         if (m_Pitch < (FX_DWORD)copy_len) {\r
192             copy_len = m_Pitch;\r
193         }\r
194         for (int row = rect.top; row < rect.bottom; row ++) {\r
195             FX_LPCBYTE src_scan = GetScanline(row) + rect.left * m_bpp / 8;\r
196             FX_LPBYTE dest_scan = (FX_LPBYTE)pNewBitmap->GetScanline(row - rect.top);\r
197             FXSYS_memcpy32(dest_scan, src_scan, copy_len);\r
198         }\r
199     }\r
200     return pNewBitmap;\r
201 }\r
202 void CFX_DIBSource::BuildPalette()\r
203 {\r
204     if (m_pPalette) {\r
205         return;\r
206     }\r
207     if (GetBPP() == 1) {\r
208         m_pPalette = FX_Alloc(FX_DWORD, 2);\r
209         if (!m_pPalette) {\r
210             return;\r
211         }\r
212         if(IsCmykImage()) {\r
213             m_pPalette[0] = 0xff;\r
214             m_pPalette[1] = 0;\r
215         } else {\r
216             m_pPalette[0] = 0xff000000;\r
217             m_pPalette[1] = 0xffffffff;\r
218         }\r
219     } else if (GetBPP() == 8) {\r
220         m_pPalette = FX_Alloc(FX_DWORD, 256);\r
221         if (!m_pPalette) {\r
222             return;\r
223         }\r
224         if(IsCmykImage()) {\r
225             for (int i = 0; i < 256; i ++) {\r
226                 m_pPalette[i] = 0xff - i;\r
227             }\r
228         } else {\r
229             for (int i = 0; i < 256; i ++) {\r
230                 m_pPalette[i] = 0xff000000 | (i * 0x10101);\r
231             }\r
232         }\r
233     }\r
234 }\r
235 FX_BOOL CFX_DIBSource::BuildAlphaMask()\r
236 {\r
237     if (m_pAlphaMask) {\r
238         return TRUE;\r
239     }\r
240     m_pAlphaMask = FX_NEW CFX_DIBitmap;\r
241     if (!m_pAlphaMask) {\r
242         return FALSE;\r
243     }\r
244     if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {\r
245         delete m_pAlphaMask;\r
246         m_pAlphaMask = NULL;\r
247         return FALSE;\r
248     }\r
249     FXSYS_memset8(m_pAlphaMask->GetBuffer(), 0xff, m_pAlphaMask->GetHeight()*m_pAlphaMask->GetPitch());\r
250     return TRUE;\r
251 }\r
252 FX_DWORD CFX_DIBSource::GetPaletteEntry(int index) const\r
253 {\r
254     ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());\r
255     if (m_pPalette) {\r
256         return m_pPalette[index];\r
257     }\r
258     if (IsCmykImage()) {\r
259         if (GetBPP() == 1) {\r
260             return index ? 0 : 0xff;\r
261         }\r
262         return 0xff - index;\r
263     }\r
264     if (GetBPP() == 1) {\r
265         return index ? 0xffffffff : 0xff000000;\r
266     }\r
267     return index * 0x10101 | 0xff000000;\r
268 }\r
269 void CFX_DIBSource::SetPaletteEntry(int index, FX_DWORD color)\r
270 {\r
271     ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());\r
272     if (m_pPalette == NULL) {\r
273         BuildPalette();\r
274     }\r
275     m_pPalette[index] = color;\r
276 }\r
277 int CFX_DIBSource::FindPalette(FX_DWORD color) const\r
278 {\r
279     ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());\r
280     if (m_pPalette == NULL) {\r
281         if (IsCmykImage()) {\r
282             if (GetBPP() == 1) {\r
283                 return ((FX_BYTE)color == 0xff) ? 0 : 1;\r
284             }\r
285             return 0xff - (FX_BYTE)color;\r
286         }\r
287         if (GetBPP() == 1) {\r
288             return ((FX_BYTE)color == 0xff) ? 1 : 0;\r
289         }\r
290         return (FX_BYTE)color;\r
291     }\r
292     int palsize = (1 << GetBPP());\r
293     for (int i = 0; i < palsize; i ++)\r
294         if (m_pPalette[i] == color) {\r
295             return i;\r
296         }\r
297     return -1;\r
298 }\r
299 void CFX_DIBitmap::Clear(FX_DWORD color)\r
300 {\r
301     if (m_pBuffer == NULL) {\r
302         return;\r
303     }\r
304     switch (GetFormat()) {\r
305         case FXDIB_1bppMask:\r
306             FXSYS_memset8(m_pBuffer, (color & 0xff000000) ? 0xff : 0, m_Pitch * m_Height);\r
307             break;\r
308         case FXDIB_1bppRgb: {\r
309                 int index = FindPalette(color);\r
310                 FXSYS_memset8(m_pBuffer, index ? 0xff : 0, m_Pitch * m_Height);\r
311                 break;\r
312             }\r
313         case FXDIB_8bppMask:\r
314             FXSYS_memset8(m_pBuffer, color >> 24, m_Pitch * m_Height);\r
315             break;\r
316         case FXDIB_8bppRgb: {\r
317                 int index = FindPalette(color);\r
318                 FXSYS_memset8(m_pBuffer, index, m_Pitch * m_Height);\r
319                 break;\r
320             }\r
321         case FXDIB_Rgb:\r
322         case FXDIB_Rgba: {\r
323                 int a, r, g, b;\r
324                 ArgbDecode(color, a, r, g, b);\r
325                 if (r == g && g == b) {\r
326                     FXSYS_memset8(m_pBuffer, r, m_Pitch * m_Height);\r
327                 } else {\r
328                     int byte_pos = 0;\r
329                     for (int col = 0; col < m_Width; col ++) {\r
330                         m_pBuffer[byte_pos++] = b;\r
331                         m_pBuffer[byte_pos++] = g;\r
332                         m_pBuffer[byte_pos++] = r;\r
333                     }\r
334                     for (int row = 1; row < m_Height; row ++) {\r
335                         FXSYS_memcpy32(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);\r
336                     }\r
337                 }\r
338                 break;\r
339             }\r
340         case FXDIB_Rgb32:\r
341         case FXDIB_Argb: {\r
342                 color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);\r
343                 for (int i = 0; i < m_Width; i ++) {\r
344                     ((FX_DWORD*)m_pBuffer)[i] = color;\r
345                 }\r
346                 for (int row = 1; row < m_Height; row ++) {\r
347                     FXSYS_memcpy32(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);\r
348                 }\r
349                 break;\r
350             }\r
351         default:\r
352             break;\r
353     }\r
354 }\r
355 void CFX_DIBSource::GetOverlapRect(int& dest_left, int& dest_top, int& width, int& height,\r
356                                    int src_width, int src_height, int& src_left, int& src_top,\r
357                                    const CFX_ClipRgn* pClipRgn)\r
358 {\r
359     if (width == 0 || height == 0) {\r
360         return;\r
361     }\r
362     ASSERT(width > 0 && height > 0);\r
363     if (dest_left > m_Width || dest_top > m_Height) {\r
364         width = 0;\r
365         height = 0;\r
366         return;\r
367     }\r
368     int x_offset = dest_left - src_left;\r
369     int y_offset = dest_top - src_top;\r
370     FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);\r
371     FX_RECT src_bound(0, 0, src_width, src_height);\r
372     src_rect.Intersect(src_bound);\r
373     FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,\r
374                       src_rect.right + x_offset, src_rect.bottom + y_offset);\r
375     FX_RECT dest_bound(0, 0, m_Width, m_Height);\r
376     dest_rect.Intersect(dest_bound);\r
377     if (pClipRgn) {\r
378         dest_rect.Intersect(pClipRgn->GetBox());\r
379     }\r
380     dest_left = dest_rect.left;\r
381     dest_top = dest_rect.top;\r
382     src_left = dest_left - x_offset;\r
383     src_top = dest_top - y_offset;\r
384     width = dest_rect.right - dest_rect.left;\r
385     height = dest_rect.bottom - dest_rect.top;\r
386 }\r
387 FX_BOOL CFX_DIBitmap::TransferBitmap(int dest_left, int dest_top, int width, int height,\r
388                                      const CFX_DIBSource* pSrcBitmap, int src_left, int src_top, void* pIccTransform)\r
389 {\r
390     if (m_pBuffer == NULL) {\r
391         return FALSE;\r
392     }\r
393     GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(), src_left, src_top, NULL);\r
394     if (width == 0 || height == 0) {\r
395         return TRUE;\r
396     }\r
397     FXDIB_Format dest_format = GetFormat();\r
398     FXDIB_Format src_format = pSrcBitmap->GetFormat();\r
399     if (dest_format == src_format && pIccTransform == NULL) {\r
400         if (GetBPP() == 1) {\r
401             for (int row = 0; row < height; row ++) {\r
402                 FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch;\r
403                 FX_LPCBYTE src_scan = pSrcBitmap->GetScanline(src_top + row);\r
404                 for (int col = 0; col < width; col ++) {\r
405                     if (src_scan[(src_left + col) / 8] & (1 << (7 - (src_left + col) % 8))) {\r
406                         dest_scan[(dest_left + col) / 8] |= 1 << (7 - (dest_left + col) % 8);\r
407                     } else {\r
408                         dest_scan[(dest_left + col) / 8] &= ~(1 << (7 - (dest_left + col) % 8));\r
409                     }\r
410                 }\r
411             }\r
412         } else {\r
413             int Bpp = GetBPP() / 8;\r
414             for (int row = 0; row < height; row ++) {\r
415                 FX_LPBYTE dest_scan = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;\r
416                 FX_LPCBYTE src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;\r
417                 FXSYS_memcpy32(dest_scan, src_scan, width * Bpp);\r
418             }\r
419         }\r
420     } else {\r
421         if (m_pPalette) {\r
422             return FALSE;\r
423         }\r
424         if (m_bpp == 8) {\r
425             dest_format = FXDIB_8bppMask;\r
426         }\r
427         FX_LPBYTE dest_buf = m_pBuffer + dest_top * m_Pitch + dest_left * GetBPP() / 8;\r
428         FX_DWORD* d_plt = NULL;\r
429         if(!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height, pSrcBitmap, src_left, src_top, d_plt, pIccTransform)) {\r
430             return FALSE;\r
431         }\r
432     }\r
433     return TRUE;\r
434 }\r
435 #ifndef _FPDFAPI_MINI_\r
436 FX_BOOL CFX_DIBitmap::TransferMask(int dest_left, int dest_top, int width, int height,\r
437                                    const CFX_DIBSource* pMask, FX_DWORD color, int src_left, int src_top, int alpha_flag, void* pIccTransform)\r
438 {\r
439     if (m_pBuffer == NULL) {\r
440         return FALSE;\r
441     }\r
442     ASSERT(HasAlpha() && (m_bpp >= 24));\r
443     ASSERT(pMask->IsAlphaMask());\r
444     if (!HasAlpha() || !pMask->IsAlphaMask() || m_bpp < 24) {\r
445         return FALSE;\r
446     }\r
447     GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), pMask->GetHeight(), src_left, src_top, NULL);\r
448     if (width == 0 || height == 0) {\r
449         return TRUE;\r
450     }\r
451     int src_pitch = pMask->GetPitch();\r
452     int src_bpp = pMask->GetBPP();\r
453     int alpha;\r
454     FX_DWORD dst_color;\r
455     if (alpha_flag >> 8) {\r
456         alpha = alpha_flag & 0xff;\r
457         dst_color = FXCMYK_TODIB(color);\r
458     } else {\r
459         alpha = FXARGB_A(color);\r
460         dst_color = FXARGB_TODIB(color);\r
461     }\r
462     FX_LPBYTE color_p = (FX_LPBYTE)&dst_color;\r
463     if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() && CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {\r
464         ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule();\r
465         pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);\r
466     } else {\r
467         if (alpha_flag >> 8 && !IsCmykImage())\r
468             AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), FXSYS_GetYValue(color), FXSYS_GetKValue(color),\r
469                                color_p[2], color_p[1], color_p[0]);\r
470         else if (!(alpha_flag >> 8) && IsCmykImage()) {\r
471             return FALSE;\r
472         }\r
473     }\r
474     if(!IsCmykImage()) {\r
475         color_p[3] = (FX_BYTE)alpha;\r
476     }\r
477     if (GetFormat() == FXDIB_Argb) {\r
478         for (int row = 0; row < height; row ++) {\r
479             FX_DWORD* dest_pos = (FX_DWORD*)(m_pBuffer + (dest_top + row) * m_Pitch + dest_left * 4);\r
480             FX_LPCBYTE src_scan = pMask->GetScanline(src_top + row);\r
481             if (src_bpp == 1) {\r
482                 for (int col = 0; col < width; col ++) {\r
483                     int src_bitpos = src_left + col;\r
484                     if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {\r
485                         *dest_pos = dst_color;\r
486                     } else {\r
487                         *dest_pos = 0;\r
488                     }\r
489                     dest_pos ++;\r
490                 }\r
491             } else {\r
492                 src_scan += src_left;\r
493                 dst_color = FXARGB_TODIB(dst_color);\r
494                 dst_color &= 0xffffff;\r
495                 for (int col = 0; col < width; col ++) {\r
496                     FXARGB_SETDIB(dest_pos++, dst_color | ((alpha * (*src_scan++) / 255) << 24));\r
497                 }\r
498             }\r
499         }\r
500     } else {\r
501         int comps = m_bpp / 8;\r
502         for (int row = 0; row < height; row ++) {\r
503             FX_LPBYTE dest_color_pos = m_pBuffer + (dest_top + row) * m_Pitch + dest_left * comps;\r
504             FX_LPBYTE dest_alpha_pos = (FX_LPBYTE)m_pAlphaMask->GetScanline(dest_top + row) + dest_left;\r
505             FX_LPCBYTE src_scan = pMask->GetScanline(src_top + row);\r
506             if (src_bpp == 1) {\r
507                 for (int col = 0; col < width; col ++) {\r
508                     int src_bitpos = src_left + col;\r
509                     if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {\r
510                         FXSYS_memcpy32(dest_color_pos, color_p, comps);\r
511                         *dest_alpha_pos = 0xff;\r
512                     } else {\r
513                         FXSYS_memset32(dest_color_pos, 0, comps);\r
514                         *dest_alpha_pos = 0;\r
515                     }\r
516                     dest_color_pos += comps;\r
517                     dest_alpha_pos ++;\r
518                 }\r
519             } else {\r
520                 src_scan += src_left;\r
521                 for (int col = 0; col < width; col ++) {\r
522                     FXSYS_memcpy32(dest_color_pos, color_p, comps);\r
523                     dest_color_pos += comps;\r
524                     *dest_alpha_pos++ = (alpha * (*src_scan++) / 255);\r
525                 }\r
526             }\r
527         }\r
528     }\r
529     return TRUE;\r
530 }\r
531 #endif\r
532 void CFX_DIBSource::CopyPalette(const FX_DWORD* pSrc, FX_DWORD size)\r
533 {\r
534     if (pSrc == NULL || GetBPP() > 8) {\r
535         if (m_pPalette) {\r
536             FX_Free(m_pPalette);\r
537         }\r
538         m_pPalette = NULL;\r
539     } else {\r
540         FX_DWORD pal_size = 1 << GetBPP();\r
541         if (m_pPalette == NULL) {\r
542             m_pPalette = FX_Alloc(FX_DWORD, pal_size);\r
543         }\r
544         if (!m_pPalette) {\r
545             return;\r
546         }\r
547         if (pal_size > size) {\r
548             pal_size = size;\r
549         }\r
550         FXSYS_memcpy32(m_pPalette, pSrc, pal_size * sizeof(FX_DWORD));\r
551     }\r
552 }\r
553 void CFX_DIBSource::GetPalette(FX_DWORD* pal, int alpha) const\r
554 {\r
555     ASSERT(GetBPP() <= 8 && !IsCmykImage());\r
556     if (GetBPP() == 1) {\r
557         pal[0] = ((m_pPalette ? m_pPalette[0] : 0xff000000) & 0xffffff) | (alpha << 24);\r
558         pal[1] = ((m_pPalette ? m_pPalette[1] : 0xffffffff) & 0xffffff) | (alpha << 24);\r
559         return;\r
560     }\r
561     if (m_pPalette) {\r
562         for (int i = 0; i < 256; i ++) {\r
563             pal[i] = (m_pPalette[i] & 0x00ffffff) | (alpha << 24);\r
564         }\r
565     } else {\r
566         for (int i = 0; i < 256; i ++) {\r
567             pal[i] = (i * 0x10101) | (alpha << 24);\r
568         }\r
569     }\r
570 }\r
571 CFX_DIBitmap* CFX_DIBSource::GetAlphaMask(const FX_RECT* pClip) const\r
572 {\r
573     ASSERT(GetFormat() == FXDIB_Argb);\r
574     FX_RECT rect(0, 0, m_Width, m_Height);\r
575     if (pClip) {\r
576         rect.Intersect(*pClip);\r
577         if (rect.IsEmpty()) {\r
578             return NULL;\r
579         }\r
580     }\r
581     CFX_DIBitmap* pMask = FX_NEW CFX_DIBitmap;\r
582     if (!pMask) {\r
583         return NULL;\r
584     }\r
585     if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask)) {\r
586         delete pMask;\r
587         return NULL;\r
588     }\r
589     for (int row = rect.top; row < rect.bottom; row ++) {\r
590         FX_LPCBYTE src_scan = GetScanline(row) + rect.left * 4 + 3;\r
591         FX_LPBYTE dest_scan = (FX_LPBYTE)pMask->GetScanline(row - rect.top);\r
592         for (int col = rect.left; col < rect.right; col ++) {\r
593             *dest_scan ++ = *src_scan;\r
594             src_scan += 4;\r
595         }\r
596     }\r
597     return pMask;\r
598 }\r
599 FX_BOOL CFX_DIBSource::CopyAlphaMask(const CFX_DIBSource* pAlphaMask, const FX_RECT* pClip)\r
600 {\r
601     if (!HasAlpha() || GetFormat() == FXDIB_Argb) {\r
602         return FALSE;\r
603     }\r
604     if (pAlphaMask) {\r
605         FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height);\r
606         if (pClip) {\r
607             rect.Intersect(*pClip);\r
608             if (rect.IsEmpty() || rect.Width() != m_Width || rect.Height() != m_Height) {\r
609                 return FALSE;\r
610             }\r
611         } else {\r
612             if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height) {\r
613                 return FALSE;\r
614             }\r
615         }\r
616         for (int row = 0; row < m_Height; row ++)\r
617             FXSYS_memcpy32((void*)m_pAlphaMask->GetScanline(row),\r
618                            pAlphaMask->GetScanline(row + rect.top) + rect.left, m_pAlphaMask->m_Pitch);\r
619     } else {\r
620         m_pAlphaMask->Clear(0xff000000);\r
621     }\r
622     return TRUE;\r
623 }\r
624 const int g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3};\r
625 FX_BOOL CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, const CFX_DIBSource* pSrcBitmap, FXDIB_Channel srcChannel)\r
626 {\r
627     if (m_pBuffer == NULL) {\r
628         return FALSE;\r
629     }\r
630     CFX_DIBSource* pSrcClone = (CFX_DIBSource*)pSrcBitmap;\r
631     CFX_DIBitmap* pDst = this;\r
632     int destOffset, srcOffset;\r
633     if (srcChannel == FXDIB_Alpha) {\r
634         if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask()) {\r
635             return FALSE;\r
636         }\r
637         if (pSrcBitmap->GetBPP() == 1) {\r
638             pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask);\r
639             if (pSrcClone == NULL) {\r
640                 return FALSE;\r
641             }\r
642         }\r
643         if(pSrcBitmap->GetFormat() == FXDIB_Argb) {\r
644             srcOffset = 3;\r
645         } else {\r
646             srcOffset = 0;\r
647         }\r
648     } else {\r
649         if (pSrcBitmap->IsAlphaMask()) {\r
650             return FALSE;\r
651         }\r
652         if (pSrcBitmap->GetBPP() < 24) {\r
653             if (pSrcBitmap->IsCmykImage()) {\r
654                 pSrcClone = pSrcBitmap->CloneConvert((FXDIB_Format)((pSrcBitmap->GetFormat() & 0xff00) | 0x20));\r
655             } else {\r
656                 pSrcClone = pSrcBitmap->CloneConvert((FXDIB_Format)((pSrcBitmap->GetFormat() & 0xff00) | 0x18));\r
657             }\r
658             if (pSrcClone == NULL) {\r
659                 return FALSE;\r
660             }\r
661         }\r
662         srcOffset = g_ChannelOffset[srcChannel];\r
663     }\r
664     if (destChannel == FXDIB_Alpha) {\r
665         if (IsAlphaMask()) {\r
666             if(!ConvertFormat(FXDIB_8bppMask)) {\r
667                 if (pSrcClone != pSrcBitmap) {\r
668                     delete pSrcClone;\r
669                 }\r
670                 return FALSE;\r
671             }\r
672             destOffset = 0;\r
673         } else {\r
674             destOffset = 0;\r
675             if(!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {\r
676                 if (pSrcClone != pSrcBitmap) {\r
677                     delete pSrcClone;\r
678                 }\r
679                 return FALSE;\r
680             }\r
681             if (GetFormat() == FXDIB_Argb) {\r
682                 destOffset = 3;\r
683             }\r
684         }\r
685     } else {\r
686         if (IsAlphaMask()) {\r
687             if (pSrcClone != pSrcBitmap) {\r
688                 delete pSrcClone;\r
689             }\r
690             return FALSE;\r
691         }\r
692         if (GetBPP() < 24) {\r
693             if (HasAlpha()) {\r
694                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {\r
695                     if (pSrcClone != pSrcBitmap) {\r
696                         delete pSrcClone;\r
697                     }\r
698                     return FALSE;\r
699                 }\r
700             } else\r
701 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
702                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {\r
703 #else\r
704                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {\r
705 #endif\r
706                     if (pSrcClone != pSrcBitmap) {\r
707                         delete pSrcClone;\r
708                     }\r
709                     return FALSE;\r
710                 }\r
711         }\r
712         destOffset = g_ChannelOffset[destChannel];\r
713     }\r
714     if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) {\r
715         CFX_DIBitmap* pAlphaMask = pSrcClone->m_pAlphaMask;\r
716         if (pSrcClone->GetWidth() != m_Width || pSrcClone->GetHeight() != m_Height) {\r
717             if (pAlphaMask) {\r
718                 pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height);\r
719                 if (pAlphaMask == NULL) {\r
720                     if (pSrcClone != pSrcBitmap) {\r
721                         delete pSrcClone;\r
722                     }\r
723                     return FALSE;\r
724                 }\r
725             }\r
726         }\r
727         if (pSrcClone != pSrcBitmap) {\r
728             pSrcClone->m_pAlphaMask = NULL;\r
729             delete pSrcClone;\r
730         }\r
731         pSrcClone = pAlphaMask;\r
732         srcOffset = 0;\r
733     } else if (pSrcClone->GetWidth() != m_Width || pSrcClone->GetHeight() != m_Height) {\r
734         CFX_DIBitmap* pSrcMatched = pSrcClone->StretchTo(m_Width, m_Height);\r
735         if (pSrcClone != pSrcBitmap) {\r
736             delete pSrcClone;\r
737         }\r
738         if (pSrcMatched == NULL) {\r
739             return FALSE;\r
740         }\r
741         pSrcClone = pSrcMatched;\r
742     }\r
743     if (destChannel == FXDIB_Alpha && m_pAlphaMask) {\r
744         pDst = m_pAlphaMask;\r
745         destOffset = 0;\r
746     }\r
747     int srcBytes = pSrcClone->GetBPP() / 8;\r
748     int destBytes = pDst->GetBPP() / 8;\r
749     for (int row = 0; row < m_Height; row ++) {\r
750         FX_LPBYTE dest_pos = (FX_LPBYTE)pDst->GetScanline(row) + destOffset;\r
751         FX_LPCBYTE src_pos = pSrcClone->GetScanline(row) + srcOffset;\r
752         for (int col = 0; col < m_Width; col ++) {\r
753             *dest_pos = *src_pos;\r
754             dest_pos += destBytes;\r
755             src_pos += srcBytes;\r
756         }\r
757     }\r
758     if (pSrcClone != pSrcBitmap && pSrcClone != pSrcBitmap->m_pAlphaMask) {\r
759         delete pSrcClone;\r
760     }\r
761     return TRUE;\r
762 }\r
763 FX_BOOL CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value)\r
764 {\r
765     if (m_pBuffer == NULL) {\r
766         return FALSE;\r
767     }\r
768     int destOffset;\r
769     if (destChannel == FXDIB_Alpha) {\r
770         if (IsAlphaMask()) {\r
771             if(!ConvertFormat(FXDIB_8bppMask)) {\r
772                 return FALSE;\r
773             }\r
774             destOffset = 0;\r
775         } else {\r
776             destOffset = 0;\r
777             if(!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {\r
778                 return FALSE;\r
779             }\r
780             if (GetFormat() == FXDIB_Argb) {\r
781                 destOffset = 3;\r
782             }\r
783         }\r
784     } else {\r
785         if (IsAlphaMask()) {\r
786             return FALSE;\r
787         }\r
788         if (GetBPP() < 24) {\r
789             if (HasAlpha()) {\r
790                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {\r
791                     return FALSE;\r
792                 }\r
793             } else\r
794 #if _FXM_PLATFORM_  == _FXM_PLATFORM_APPLE_\r
795                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {\r
796                     return FALSE;\r
797                 }\r
798 #else\r
799                 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {\r
800                     return FALSE;\r
801                 }\r
802 #endif\r
803         }\r
804         destOffset = g_ChannelOffset[destChannel];\r
805     }\r
806     int Bpp = GetBPP() / 8;\r
807     if (Bpp == 1) {\r
808         FXSYS_memset8(m_pBuffer, value, m_Height * m_Pitch);\r
809         return TRUE;\r
810     }\r
811     if (destChannel == FXDIB_Alpha && m_pAlphaMask) {\r
812         FXSYS_memset8(m_pAlphaMask->GetBuffer(), value, m_pAlphaMask->GetHeight()*m_pAlphaMask->GetPitch());\r
813         return TRUE;\r
814     }\r
815     for (int row = 0; row < m_Height; row ++) {\r
816         FX_LPBYTE scan_line = m_pBuffer + row * m_Pitch + destOffset;\r
817         for (int col = 0; col < m_Width; col ++) {\r
818             *scan_line = value;\r
819             scan_line += Bpp;\r
820         }\r
821     }\r
822     return TRUE;\r
823 }\r
824 FX_BOOL CFX_DIBitmap::MultiplyAlpha(const CFX_DIBSource* pSrcBitmap)\r
825 {\r
826     if (m_pBuffer == NULL) {\r
827         return FALSE;\r
828     }\r
829     ASSERT(pSrcBitmap->IsAlphaMask());\r
830     if (!pSrcBitmap->IsAlphaMask()) {\r
831         return FALSE;\r
832     }\r
833     if (!IsAlphaMask() && !HasAlpha()) {\r
834         return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha);\r
835     }\r
836     CFX_DIBitmap* pSrcClone = (CFX_DIBitmap*)pSrcBitmap;\r
837     if (pSrcBitmap->GetWidth() != m_Width || pSrcBitmap->GetHeight() != m_Height) {\r
838         pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height);\r
839         ASSERT(pSrcClone != NULL);\r
840         if (pSrcClone == NULL) {\r
841             return FALSE;\r
842         }\r
843     }\r
844     if (IsAlphaMask()) {\r
845         if(!ConvertFormat(FXDIB_8bppMask)) {\r
846             if (pSrcClone != pSrcBitmap) {\r
847                 delete pSrcClone;\r
848             }\r
849             return FALSE;\r
850         }\r
851         for (int row = 0; row < m_Height; row ++) {\r
852             FX_LPBYTE dest_scan = m_pBuffer + m_Pitch * row;\r
853             FX_LPBYTE src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;\r
854             if (pSrcClone->GetBPP() == 1) {\r
855                 for (int col = 0; col < m_Width; col ++) {\r
856                     if (!((1 << (7 - col % 8)) & src_scan[col / 8])) {\r
857                         dest_scan[col] = 0;\r
858                     }\r
859                 }\r
860             } else {\r
861                 for (int col = 0; col < m_Width; col ++) {\r
862                     *dest_scan = (*dest_scan) * src_scan[col] / 255;\r
863                     dest_scan ++;\r
864                 }\r
865             }\r
866         }\r
867     } else {\r
868         if(GetFormat() == FXDIB_Argb) {\r
869             if (pSrcClone->GetBPP() == 1) {\r
870                 if (pSrcClone != pSrcBitmap) {\r
871                     delete pSrcClone;\r
872                 }\r
873                 return FALSE;\r
874             }\r
875             for (int row = 0; row < m_Height; row ++) {\r
876                 FX_LPBYTE dest_scan = m_pBuffer + m_Pitch * row + 3;\r
877                 FX_LPBYTE src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;\r
878                 for (int col = 0; col < m_Width; col ++) {\r
879                     *dest_scan = (*dest_scan) * src_scan[col] / 255;\r
880                     dest_scan += 4;\r
881                 }\r
882             }\r
883         } else {\r
884             m_pAlphaMask->MultiplyAlpha(pSrcClone);\r
885         }\r
886     }\r
887     if (pSrcClone != pSrcBitmap) {\r
888         delete pSrcClone;\r
889     }\r
890     return TRUE;\r
891 }\r
892 FX_BOOL CFX_DIBitmap::GetGrayData(void* pIccTransform)\r
893 {\r
894     if (m_pBuffer == NULL) {\r
895         return FALSE;\r
896     }\r
897     switch (GetFormat()) {\r
898         case FXDIB_1bppRgb: {\r
899                 if (m_pPalette == NULL) {\r
900                     return FALSE;\r
901                 }\r
902                 FX_BYTE gray[2];\r
903                 for (int i = 0; i < 2; i ++) {\r
904                     int r = (FX_BYTE)(m_pPalette[i] >> 16);\r
905                     int g = (FX_BYTE)(m_pPalette[i] >> 8);\r
906                     int b = (FX_BYTE)m_pPalette[i];\r
907                     gray[i] = (FX_BYTE)FXRGB2GRAY(r, g, b);\r
908                 }\r
909                 CFX_DIBitmap* pMask = FX_NEW CFX_DIBitmap;\r
910                 if (!pMask) {\r
911                     return FALSE;\r
912                 }\r
913                 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {\r
914                     delete pMask;\r
915                     return FALSE;\r
916                 }\r
917                 FXSYS_memset8(pMask->GetBuffer(), gray[0], pMask->GetPitch() * m_Height);\r
918                 for (int row = 0; row < m_Height; row ++) {\r
919                     FX_LPBYTE src_pos = m_pBuffer + row * m_Pitch;\r
920                     FX_LPBYTE dest_pos = (FX_LPBYTE)pMask->GetScanline(row);\r
921                     for (int col = 0; col < m_Width; col ++) {\r
922                         if (src_pos[col / 8] & (1 << (7 - col % 8))) {\r
923                             *dest_pos = gray[1];\r
924                         }\r
925                         dest_pos ++;\r
926                     }\r
927                 }\r
928                 TakeOver(pMask);\r
929                 delete pMask;\r
930                 break;\r
931             }\r
932         case FXDIB_8bppRgb: {\r
933                 if (m_pPalette == NULL) {\r
934                     return FALSE;\r
935                 }\r
936                 FX_BYTE gray[256];\r
937                 for (int i = 0; i < 256; i ++) {\r
938                     int r = (FX_BYTE)(m_pPalette[i] >> 16);\r
939                     int g = (FX_BYTE)(m_pPalette[i] >> 8);\r
940                     int b = (FX_BYTE)m_pPalette[i];\r
941                     gray[i] = (FX_BYTE)FXRGB2GRAY(r, g, b);\r
942                 }\r
943                 CFX_DIBitmap* pMask = FX_NEW CFX_DIBitmap;\r
944                 if (!pMask) {\r
945                     return FALSE;\r
946                 }\r
947                 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {\r
948                     delete pMask;\r
949                     return FALSE;\r
950                 }\r
951                 for (int row = 0; row < m_Height; row ++) {\r
952                     FX_LPBYTE dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();\r
953                     FX_LPBYTE src_pos = m_pBuffer + row * m_Pitch;\r
954                     for (int col = 0; col < m_Width; col ++) {\r
955                         *dest_pos ++ = gray[*src_pos ++];\r
956                     }\r
957                 }\r
958                 TakeOver(pMask);\r
959                 delete pMask;\r
960                 break;\r
961             }\r
962         case FXDIB_Rgb: {\r
963                 CFX_DIBitmap* pMask = FX_NEW CFX_DIBitmap;\r
964                 if (!pMask) {\r
965                     return FALSE;\r
966                 }\r
967                 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {\r
968                     delete pMask;\r
969                     return FALSE;\r
970                 }\r
971                 for (int row = 0; row < m_Height; row ++) {\r
972                     FX_LPBYTE src_pos = m_pBuffer + row * m_Pitch;\r
973                     FX_LPBYTE dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();\r
974                     for (int col = 0; col < m_Width; col ++) {\r
975                         *dest_pos ++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);\r
976                         src_pos += 3;\r
977                     }\r
978                 }\r
979                 TakeOver(pMask);\r
980                 delete pMask;\r
981                 break;\r
982             }\r
983         case FXDIB_Rgb32: {\r
984                 CFX_DIBitmap* pMask = FX_NEW CFX_DIBitmap;\r
985                 if (!pMask) {\r
986                     return FALSE;\r
987                 }\r
988                 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {\r
989                     delete pMask;\r
990                     return FALSE;\r
991                 }\r
992                 for (int row = 0; row < m_Height; row ++) {\r
993                     FX_LPBYTE src_pos = m_pBuffer + row * m_Pitch;\r
994                     FX_LPBYTE dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();\r
995                     for (int col = 0; col < m_Width; col ++) {\r
996                         *dest_pos ++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);\r
997                         src_pos += 4;\r
998                     }\r
999                 }\r
1000                 TakeOver(pMask);\r
1001                 delete pMask;\r
1002                 break;\r
1003             }\r
1004         default:\r
1005             return FALSE;\r
1006     }\r
1007     return TRUE;\r
1008 }\r
1009 FX_BOOL CFX_DIBitmap::MultiplyAlpha(int alpha)\r
1010 {\r
1011     if (m_pBuffer == NULL) {\r
1012         return FALSE;\r
1013     }\r
1014     switch (GetFormat()) {\r
1015         case FXDIB_1bppMask:\r
1016             if (!ConvertFormat(FXDIB_8bppMask)) {\r
1017                 return FALSE;\r
1018             }\r
1019             MultiplyAlpha(alpha);\r
1020             break;\r
1021         case FXDIB_8bppMask: {\r
1022                 for (int row = 0; row < m_Height; row ++) {\r
1023                     FX_LPBYTE scan_line = m_pBuffer + row * m_Pitch;\r
1024                     for (int col = 0; col < m_Width; col ++) {\r
1025                         scan_line[col] = scan_line[col] * alpha / 255;\r
1026                     }\r
1027                 }\r
1028                 break;\r
1029             }\r
1030         case FXDIB_Argb: {\r
1031                 for (int row = 0; row < m_Height; row ++) {\r
1032                     FX_LPBYTE scan_line = m_pBuffer + row * m_Pitch + 3;\r
1033                     for (int col = 0; col < m_Width; col ++) {\r
1034                         *scan_line = (*scan_line) * alpha / 255;\r
1035                         scan_line += 4;\r
1036                     }\r
1037                 }\r
1038                 break;\r
1039             }\r
1040         default:\r
1041             if (HasAlpha()) {\r
1042                 m_pAlphaMask->MultiplyAlpha(alpha);\r
1043             } else if (IsCmykImage()) {\r
1044                 if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) {\r
1045                     return FALSE;\r
1046                 }\r
1047                 m_pAlphaMask->MultiplyAlpha(alpha);\r
1048             } else {\r
1049                 if (!ConvertFormat(FXDIB_Argb)) {\r
1050                     return FALSE;\r
1051                 }\r
1052                 MultiplyAlpha(alpha);\r
1053             }\r
1054             break;\r
1055     }\r
1056     return TRUE;\r
1057 }\r
1058 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)\r
1059 FX_DWORD CFX_DIBitmap::GetPixel(int x, int y) const\r
1060 {\r
1061     if (m_pBuffer == NULL) {\r
1062         return 0;\r
1063     }\r
1064     FX_LPBYTE pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;\r
1065     switch (GetFormat()) {\r
1066         case FXDIB_1bppMask: {\r
1067                 if ((*pos) & (1 << (7 - x % 8))) {\r
1068                     return 0xff000000;\r
1069                 }\r
1070                 return 0;\r
1071             }\r
1072         case FXDIB_1bppRgb: {\r
1073                 if ((*pos) & (1 << (7 - x % 8))) {\r
1074                     return m_pPalette ? m_pPalette[1] : 0xffffffff;\r
1075                 } else {\r
1076                     return m_pPalette ? m_pPalette[0] : 0xff000000;\r
1077                 }\r
1078                 break;\r
1079             }\r
1080         case FXDIB_8bppMask:\r
1081             return (*pos) << 24;\r
1082         case FXDIB_8bppRgb:\r
1083             return m_pPalette ? m_pPalette[*pos] : (0xff000000 | ((*pos) * 0x10101));\r
1084         case FXDIB_Rgb:\r
1085         case FXDIB_Rgba:\r
1086         case FXDIB_Rgb32:\r
1087             return FXARGB_GETDIB(pos) | 0xff000000;\r
1088         case FXDIB_Argb:\r
1089             return FXARGB_GETDIB(pos);\r
1090         default:\r
1091             break;\r
1092     }\r
1093     return 0;\r
1094 }\r
1095 #endif\r
1096 void CFX_DIBitmap::SetPixel(int x, int y, FX_DWORD color)\r
1097 {\r
1098     if (m_pBuffer == NULL) {\r
1099         return;\r
1100     }\r
1101     if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) {\r
1102         return;\r
1103     }\r
1104     FX_LPBYTE pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;\r
1105     switch (GetFormat()) {\r
1106         case FXDIB_1bppMask:\r
1107             if (color >> 24) {\r
1108                 *pos |= 1 << (7 - x % 8);\r
1109             } else {\r
1110                 *pos &= ~(1 << (7 - x % 8));\r
1111             }\r
1112             break;\r
1113         case FXDIB_1bppRgb:\r
1114             if (m_pPalette) {\r
1115                 if (color == m_pPalette[1]) {\r
1116                     *pos |= 1 << (7 - x % 8);\r
1117                 } else {\r
1118                     *pos &= ~(1 << (7 - x % 8));\r
1119                 }\r
1120             } else {\r
1121                 if (color == 0xffffffff) {\r
1122                     *pos |= 1 << (7 - x % 8);\r
1123                 } else {\r
1124                     *pos &= ~(1 << (7 - x % 8));\r
1125                 }\r
1126             }\r
1127             break;\r
1128         case FXDIB_8bppMask:\r
1129             *pos = (FX_BYTE)(color >> 24);\r
1130             break;\r
1131         case FXDIB_8bppRgb: {\r
1132                 if (m_pPalette) {\r
1133                     for (int i = 0; i < 256; i ++) {\r
1134                         if (m_pPalette[i] == color) {\r
1135                             *pos = (FX_BYTE)i;\r
1136                             return;\r
1137                         }\r
1138                     }\r
1139                     *pos = 0;\r
1140                 } else {\r
1141                     *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));\r
1142                 }\r
1143                 break;\r
1144             }\r
1145         case FXDIB_Rgb:\r
1146         case FXDIB_Rgb32: {\r
1147                 int alpha = FXARGB_A(color);\r
1148                 pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255;\r
1149                 pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255;\r
1150                 pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255;\r
1151                 break;\r
1152             }\r
1153         case FXDIB_Rgba: {\r
1154                 pos[0] = FXARGB_B(color);\r
1155                 pos[1] = FXARGB_G(color);\r
1156                 pos[2] = FXARGB_R(color);\r
1157                 break;\r
1158             }\r
1159         case FXDIB_Argb:\r
1160             FXARGB_SETDIB(pos, color);\r
1161             break;\r
1162         default:\r
1163             break;\r
1164     }\r
1165 }\r
1166 void CFX_DIBitmap::DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp,\r
1167                                       int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const\r
1168 {\r
1169     if (m_pBuffer == NULL) {\r
1170         return;\r
1171     }\r
1172     int src_Bpp = m_bpp / 8;\r
1173     FX_LPBYTE scanline = m_pBuffer + line * m_Pitch;\r
1174     if (src_Bpp == 0) {\r
1175         for (int i = 0; i < clip_width; i ++) {\r
1176             FX_DWORD dest_x = clip_left + i;\r
1177             FX_DWORD src_x = dest_x * m_Width / dest_width;\r
1178             if (bFlipX) {\r
1179                 src_x = m_Width - src_x - 1;\r
1180             }\r
1181 #ifdef FOXIT_CHROME_BUILD\r
1182             src_x %= m_Width;\r
1183 #endif\r
1184             dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0;\r
1185         }\r
1186     } else if (src_Bpp == 1) {\r
1187         for (int i = 0; i < clip_width; i ++) {\r
1188             FX_DWORD dest_x = clip_left + i;\r
1189             FX_DWORD src_x = dest_x * m_Width / dest_width;\r
1190             if (bFlipX) {\r
1191                 src_x = m_Width - src_x - 1;\r
1192             }\r
1193 #ifdef FOXIT_CHROME_BUILD\r
1194             src_x %= m_Width;\r
1195 #endif\r
1196             int dest_pos = i;\r
1197             if (m_pPalette) {\r
1198                 if (!IsCmykImage()) {\r
1199                     dest_pos *= 3;\r
1200                     FX_ARGB argb = m_pPalette[scanline[src_x]];\r
1201                     dest_scan[dest_pos] = FXARGB_B(argb);\r
1202                     dest_scan[dest_pos + 1] = FXARGB_G(argb);\r
1203                     dest_scan[dest_pos + 2] = FXARGB_R(argb);\r
1204                 } else {\r
1205                     dest_pos *= 4;\r
1206                     FX_CMYK cmyk = m_pPalette[scanline[src_x]];\r
1207                     dest_scan[dest_pos] = FXSYS_GetCValue(cmyk);\r
1208                     dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk);\r
1209                     dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk);\r
1210                     dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk);\r
1211                 }\r
1212             } else {\r
1213                 dest_scan[dest_pos] = scanline[src_x];\r
1214             }\r
1215         }\r
1216     } else {\r
1217         for (int i = 0; i < clip_width; i ++) {\r
1218             FX_DWORD dest_x = clip_left + i;\r
1219             FX_DWORD src_x = bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp : (dest_x * m_Width / dest_width) * src_Bpp;\r
1220 #ifdef FOXIT_CHROME_BUILD\r
1221             src_x %= m_Width * src_Bpp;\r
1222 #endif\r
1223             int dest_pos = i * src_Bpp;\r
1224             for (int b = 0; b < src_Bpp; b ++) {\r
1225                 dest_scan[dest_pos + b] = scanline[src_x + b];\r
1226             }\r
1227         }\r
1228     }\r
1229 }\r
1230 FX_BOOL CFX_DIBitmap::ConvertColorScale(FX_DWORD forecolor, FX_DWORD backcolor)\r
1231 {\r
1232     ASSERT(!IsAlphaMask());\r
1233     if (m_pBuffer == NULL || IsAlphaMask()) {\r
1234         return FALSE;\r
1235     }\r
1236     int fc, fm, fy, fk, bc, bm, by, bk;\r
1237     int fr, fg, fb, br, bg, bb;\r
1238     FX_BOOL isCmykImage = IsCmykImage();\r
1239     if (isCmykImage) {\r
1240         fc = FXSYS_GetCValue(forecolor);\r
1241         fm = FXSYS_GetMValue(forecolor);\r
1242         fy = FXSYS_GetYValue(forecolor);\r
1243         fk = FXSYS_GetKValue(forecolor);\r
1244         bc = FXSYS_GetCValue(backcolor);\r
1245         bm = FXSYS_GetMValue(backcolor);\r
1246         by = FXSYS_GetYValue(backcolor);\r
1247         bk = FXSYS_GetKValue(backcolor);\r
1248     } else {\r
1249         fr = FXSYS_GetRValue(forecolor);\r
1250         fg = FXSYS_GetGValue(forecolor);\r
1251         fb = FXSYS_GetBValue(forecolor);\r
1252         br = FXSYS_GetRValue(backcolor);\r
1253         bg = FXSYS_GetGValue(backcolor);\r
1254         bb = FXSYS_GetBValue(backcolor);\r
1255     }\r
1256     if (m_bpp <= 8) {\r
1257         if (isCmykImage) {\r
1258             if (forecolor == 0xff && backcolor == 0 && m_pPalette == NULL) {\r
1259                 return TRUE;\r
1260             }\r
1261         } else if (forecolor == 0 && backcolor == 0xffffff && m_pPalette == NULL) {\r
1262             return TRUE;\r
1263         }\r
1264         if (m_pPalette == NULL) {\r
1265             BuildPalette();\r
1266         }\r
1267         int size = 1 << m_bpp;\r
1268         if (isCmykImage) {\r
1269             for (int i = 0; i < size; i ++) {\r
1270                 FX_BYTE b, g, r;\r
1271                 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette[i]), FXSYS_GetMValue(m_pPalette[i]), FXSYS_GetYValue(m_pPalette[i]), FXSYS_GetKValue(m_pPalette[i]),\r
1272                                    r, g, b);\r
1273                 int gray = 255 - FXRGB2GRAY(r, g, b);\r
1274                 m_pPalette[i] = CmykEncode(bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255,\r
1275                                            by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255);\r
1276             }\r
1277         } else\r
1278             for (int i = 0; i < size; i ++) {\r
1279                 int gray = FXRGB2GRAY(FXARGB_R(m_pPalette[i]), FXARGB_G(m_pPalette[i]), FXARGB_B(m_pPalette[i]));\r
1280                 m_pPalette[i] = FXARGB_MAKE(0xff, br + (fr - br) * gray / 255, bg + (fg - bg) * gray / 255,\r
1281                                             bb + (fb - bb) * gray / 255);\r
1282             }\r
1283         return TRUE;\r
1284     }\r
1285     if (isCmykImage) {\r
1286         if (forecolor == 0xff && backcolor == 0x00) {\r
1287             for (int row = 0; row < m_Height; row ++) {\r
1288                 FX_LPBYTE scanline = m_pBuffer + row * m_Pitch;\r
1289                 for (int col = 0; col < m_Width; col ++) {\r
1290                     FX_BYTE b, g, r;\r
1291                     AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],\r
1292                                        r, g, b);\r
1293                     *scanline ++ = 0;\r
1294                     *scanline ++ = 0;\r
1295                     *scanline ++ = 0;\r
1296                     *scanline ++ = 255 - FXRGB2GRAY(r, g, b);\r
1297                 }\r
1298             }\r
1299             return TRUE;\r
1300         }\r
1301     } else if (forecolor == 0 && backcolor == 0xffffff) {\r
1302         for (int row = 0; row < m_Height; row ++) {\r
1303             FX_LPBYTE scanline = m_pBuffer + row * m_Pitch;\r
1304             int gap = m_bpp / 8 - 2;\r
1305             for (int col = 0; col < m_Width; col ++) {\r
1306                 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);\r
1307                 *scanline ++ = gray;\r
1308                 *scanline ++ = gray;\r
1309                 *scanline    = gray;\r
1310                 scanline += gap;\r
1311             }\r
1312         }\r
1313         return TRUE;\r
1314     }\r
1315     if (isCmykImage) {\r
1316         for (int row = 0; row < m_Height; row ++) {\r
1317             FX_LPBYTE scanline = m_pBuffer + row * m_Pitch;\r
1318             for (int col = 0; col < m_Width; col ++) {\r
1319                 FX_BYTE b, g, r;\r
1320                 AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],\r
1321                                    r, g, b);\r
1322                 int gray = 255 - FXRGB2GRAY(r, g, b);\r
1323                 *scanline ++ = bc + (fc - bc) * gray / 255;\r
1324                 *scanline ++ = bm + (fm - bm) * gray / 255;\r
1325                 *scanline ++ = by + (fy - by) * gray / 255;\r
1326                 *scanline ++ = bk + (fk - bk) * gray / 255;\r
1327             }\r
1328         }\r
1329     } else\r
1330         for (int row = 0; row < m_Height; row ++) {\r
1331             FX_LPBYTE scanline = m_pBuffer + row * m_Pitch;\r
1332             int gap = m_bpp / 8 - 2;\r
1333             for (int col = 0; col < m_Width; col ++) {\r
1334                 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);\r
1335                 *scanline ++ = bb + (fb - bb) * gray / 255;\r
1336                 *scanline ++ = bg + (fg - bg) * gray / 255;\r
1337                 *scanline    = br + (fr - br) * gray / 255;\r
1338                 scanline += gap;\r
1339             }\r
1340         }\r
1341     return TRUE;\r
1342 }\r
1343 FX_BOOL CFX_DIBitmap::DitherFS(const FX_DWORD* pPalette, int pal_size, const FX_RECT* pRect)\r
1344 {\r
1345     if (m_pBuffer == NULL) {\r
1346         return FALSE;\r
1347     }\r
1348     if (m_bpp != 8 && m_pPalette != NULL && m_AlphaFlag != 0) {\r
1349         return FALSE;\r
1350     }\r
1351     if (m_Width < 4 && m_Height < 4) {\r
1352         return FALSE;\r
1353     }\r
1354     FX_RECT rect(0, 0, m_Width, m_Height);\r
1355     if (pRect) {\r
1356         rect.Intersect(*pRect);\r
1357     }\r
1358     FX_BYTE translate[256];\r
1359     for (int i = 0; i < 256; i ++) {\r
1360         int err2 = 65536;\r
1361         for (int j = 0; j < pal_size; j ++) {\r
1362             FX_BYTE entry = (FX_BYTE)pPalette[j];\r
1363             int err = (int)entry - i;\r
1364             if (err * err < err2) {\r
1365                 err2 = err * err;\r
1366                 translate[i] = entry;\r
1367             }\r
1368         }\r
1369     }\r
1370     for (int row = rect.top; row < rect.bottom; row ++) {\r
1371         FX_LPBYTE scan = m_pBuffer + row * m_Pitch;\r
1372         FX_LPBYTE next_scan = m_pBuffer + (row + 1) * m_Pitch;\r
1373         for (int col = rect.left; col < rect.right; col ++) {\r
1374             int src_pixel = scan[col];\r
1375             int dest_pixel = translate[src_pixel];\r
1376             scan[col] = (FX_BYTE)dest_pixel;\r
1377             int error = -dest_pixel + src_pixel;\r
1378             if (col < rect.right - 1) {\r
1379                 int src = scan[col + 1];\r
1380                 src += error * 7 / 16;\r
1381                 if (src > 255) {\r
1382                     scan[col + 1] = 255;\r
1383                 } else if (src < 0) {\r
1384                     scan[col + 1] = 0;\r
1385                 } else {\r
1386                     scan[col + 1] = src;\r
1387                 }\r
1388             }\r
1389             if (col < rect.right - 1 && row < rect.bottom - 1) {\r
1390                 int src = next_scan[col + 1];\r
1391                 src += error * 1 / 16;\r
1392                 if (src > 255) {\r
1393                     next_scan[col + 1] = 255;\r
1394                 } else if (src < 0) {\r
1395                     next_scan[col + 1] = 0;\r
1396                 } else {\r
1397                     next_scan[col + 1] = src;\r
1398                 }\r
1399             }\r
1400             if (row < rect.bottom - 1) {\r
1401                 int src = next_scan[col];\r
1402                 src += error * 5 / 16;\r
1403                 if (src > 255) {\r
1404                     next_scan[col] = 255;\r
1405                 } else if (src < 0) {\r
1406                     next_scan[col] = 0;\r
1407                 } else {\r
1408                     next_scan[col] = src;\r
1409                 }\r
1410             }\r
1411             if (col > rect.left && row < rect.bottom - 1) {\r
1412                 int src = next_scan[col - 1];\r
1413                 src += error * 3 / 16;\r
1414                 if (src > 255) {\r
1415                     next_scan[col - 1] = 255;\r
1416                 } else if (src < 0) {\r
1417                     next_scan[col - 1] = 0;\r
1418                 } else {\r
1419                     next_scan[col - 1] = src;\r
1420                 }\r
1421             }\r
1422         }\r
1423     }\r
1424     return TRUE;\r
1425 }\r
1426 CFX_DIBitmap* CFX_DIBSource::FlipImage(FX_BOOL bXFlip, FX_BOOL bYFlip) const\r
1427 {\r
1428     CFX_DIBitmap* pFlipped = FX_NEW CFX_DIBitmap;\r
1429     if (!pFlipped) {\r
1430         return NULL;\r
1431     }\r
1432     if (!pFlipped->Create(m_Width, m_Height, GetFormat())) {\r
1433         delete pFlipped;\r
1434         return NULL;\r
1435     }\r
1436     pFlipped->CopyPalette(m_pPalette);\r
1437     FX_LPBYTE pDestBuffer = pFlipped->GetBuffer();\r
1438     int Bpp = m_bpp / 8;\r
1439     for (int row = 0; row < m_Height; row ++) {\r
1440         FX_LPCBYTE src_scan = GetScanline(row);\r
1441         FX_LPBYTE dest_scan = pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);\r
1442         if (!bXFlip) {\r
1443             FXSYS_memcpy32(dest_scan, src_scan, m_Pitch);\r
1444             continue;\r
1445         }\r
1446         if (m_bpp == 1) {\r
1447             FXSYS_memset32(dest_scan, 0, m_Pitch);\r
1448             for (int col = 0; col < m_Width; col ++)\r
1449                 if (src_scan[col / 8] & (1 << (7 - col % 8))) {\r
1450                     int dest_col = m_Width - col - 1;\r
1451                     dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));\r
1452                 }\r
1453         } else {\r
1454             dest_scan += (m_Width - 1) * Bpp;\r
1455             if (Bpp == 1) {\r
1456                 for (int col = 0; col < m_Width; col ++) {\r
1457                     *dest_scan = *src_scan;\r
1458                     dest_scan --;\r
1459                     src_scan ++;\r
1460                 }\r
1461             } else if (Bpp == 3) {\r
1462                 for (int col = 0; col < m_Width; col ++) {\r
1463                     dest_scan[0] = src_scan[0];\r
1464                     dest_scan[1] = src_scan[1];\r
1465                     dest_scan[2] = src_scan[2];\r
1466                     dest_scan -= 3;\r
1467                     src_scan += 3;\r
1468                 }\r
1469             } else {\r
1470                 ASSERT(Bpp == 4);\r
1471                 for (int col = 0; col < m_Width; col ++) {\r
1472                     *(FX_DWORD*)dest_scan = *(FX_DWORD*)src_scan;\r
1473                     dest_scan -= 4;\r
1474                     src_scan += 4;\r
1475                 }\r
1476             }\r
1477         }\r
1478     }\r
1479     if (m_pAlphaMask) {\r
1480         pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();\r
1481         FX_DWORD dest_pitch = pFlipped->m_pAlphaMask->GetPitch();\r
1482         for (int row = 0; row < m_Height; row ++) {\r
1483             FX_LPCBYTE src_scan = m_pAlphaMask->GetScanline(row);\r
1484             FX_LPBYTE dest_scan = pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);\r
1485             if (!bXFlip) {\r
1486                 FXSYS_memcpy32(dest_scan, src_scan, dest_pitch);\r
1487                 continue;\r
1488             }\r
1489             dest_scan += (m_Width - 1);\r
1490             for (int col = 0; col < m_Width; col ++) {\r
1491                 *dest_scan = *src_scan;\r
1492                 dest_scan --;\r
1493                 src_scan ++;\r
1494             }\r
1495         }\r
1496     }\r
1497     return pFlipped;\r
1498 }\r
1499 CFX_DIBExtractor::CFX_DIBExtractor(const CFX_DIBSource* pSrc)\r
1500 {\r
1501     m_pBitmap = NULL;\r
1502     if (pSrc->GetBuffer() == NULL) {\r
1503         m_pBitmap = pSrc->Clone();\r
1504     } else {\r
1505         m_pBitmap = FX_NEW CFX_DIBitmap;\r
1506         if (!m_pBitmap) {\r
1507             return;\r
1508         }\r
1509         if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat(), pSrc->GetBuffer())) {\r
1510             delete m_pBitmap;\r
1511             m_pBitmap = NULL;\r
1512             return;\r
1513         }\r
1514         m_pBitmap->CopyPalette(pSrc->GetPalette());\r
1515         m_pBitmap->CopyAlphaMask(pSrc->m_pAlphaMask);\r
1516     }\r
1517 }\r
1518 CFX_DIBExtractor::~CFX_DIBExtractor()\r
1519 {\r
1520     if (m_pBitmap) {\r
1521         delete m_pBitmap;\r
1522     }\r
1523 }\r
1524 CFX_FilteredDIB::CFX_FilteredDIB()\r
1525 {\r
1526     m_pScanline = NULL;\r
1527     m_pSrc = NULL;\r
1528 }\r
1529 CFX_FilteredDIB::~CFX_FilteredDIB()\r
1530 {\r
1531     if (m_pSrc && m_bAutoDropSrc) {\r
1532         delete m_pSrc;\r
1533     }\r
1534     if (m_pScanline) {\r
1535         FX_Free(m_pScanline);\r
1536     }\r
1537 }\r
1538 void CFX_FilteredDIB::LoadSrc(const CFX_DIBSource* pSrc, FX_BOOL bAutoDropSrc)\r
1539 {\r
1540     m_pSrc = pSrc;\r
1541     m_bAutoDropSrc = bAutoDropSrc;\r
1542     m_Width = pSrc->GetWidth();\r
1543     m_Height = pSrc->GetHeight();\r
1544     FXDIB_Format format = GetDestFormat();\r
1545     m_bpp = (FX_BYTE)format;\r
1546     m_AlphaFlag = (FX_BYTE)(format >> 8);\r
1547     m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4;\r
1548     m_pPalette = GetDestPalette();\r
1549     m_pScanline = FX_Alloc(FX_BYTE, m_Pitch);\r
1550 }\r
1551 FX_LPCBYTE CFX_FilteredDIB::GetScanline(int line) const\r
1552 {\r
1553     TranslateScanline(m_pScanline, m_pSrc->GetScanline(line));\r
1554     return m_pScanline;\r
1555 }\r
1556 void CFX_FilteredDIB::DownSampleScanline(int line, FX_LPBYTE dest_scan, int dest_bpp,\r
1557         int dest_width, FX_BOOL bFlipX, int clip_left, int clip_width) const\r
1558 {\r
1559     m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX, clip_left, clip_width);\r
1560     TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp);\r
1561 }\r
1562 CFX_ImageRenderer::CFX_ImageRenderer()\r
1563 {\r
1564     m_Status = 0;\r
1565     m_pTransformer = NULL;\r
1566     m_bRgbByteOrder = FALSE;\r
1567     m_BlendType = FXDIB_BLEND_NORMAL;\r
1568 }\r
1569 CFX_ImageRenderer::~CFX_ImageRenderer()\r
1570 {\r
1571     if (m_pTransformer) {\r
1572         delete m_pTransformer;\r
1573     }\r
1574 }\r
1575 extern FX_RECT _FXDIB_SwapClipBox(FX_RECT& clip, int width, int height, FX_BOOL bFlipX, FX_BOOL bFlipY);\r
1576 FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, const CFX_ClipRgn* pClipRgn,\r
1577                                  const CFX_DIBSource* pSource, int bitmap_alpha,\r
1578                                  FX_DWORD mask_color, const CFX_AffineMatrix* pMatrix,\r
1579                                  FX_DWORD dib_flags, FX_BOOL bRgbByteOrder,\r
1580                                  int alpha_flag, void* pIccTransform, int blend_type)\r
1581 {\r
1582     m_Matrix = *pMatrix;\r
1583     CFX_FloatRect image_rect_f = m_Matrix.GetUnitRect();\r
1584     FX_RECT image_rect = image_rect_f.GetOutterRect();\r
1585     m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(), pDevice->GetHeight());\r
1586     m_ClipBox.Intersect(image_rect);\r
1587     if (m_ClipBox.IsEmpty()) {\r
1588         return FALSE;\r
1589     }\r
1590     m_pDevice = pDevice;\r
1591     m_pClipRgn = pClipRgn;\r
1592     m_MaskColor = mask_color;\r
1593     m_BitmapAlpha = bitmap_alpha;\r
1594     m_Matrix = *pMatrix;\r
1595     m_Flags = dib_flags;\r
1596     m_AlphaFlag = alpha_flag;\r
1597     m_pIccTransform = pIccTransform;\r
1598     m_bRgbByteOrder = bRgbByteOrder;\r
1599     m_BlendType = blend_type;\r
1600     FX_BOOL ret = TRUE;\r
1601     if ((FXSYS_fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) ||\r
1602             (FXSYS_fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0) ) {\r
1603         if (FXSYS_fabs(m_Matrix.a) < FXSYS_fabs(m_Matrix.b) / 20 && FXSYS_fabs(m_Matrix.d) < FXSYS_fabs(m_Matrix.c) / 20 &&\r
1604                 FXSYS_fabs(m_Matrix.a) < 0.5f && FXSYS_fabs(m_Matrix.d) < 0.5f) {\r
1605             int dest_width = image_rect.Width();\r
1606             int dest_height = image_rect.Height();\r
1607             FX_RECT bitmap_clip = m_ClipBox;\r
1608             bitmap_clip.Offset(-image_rect.left, -image_rect.top);\r
1609             bitmap_clip = _FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height, m_Matrix.c > 0, m_Matrix.b < 0);\r
1610             m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, TRUE,\r
1611                                m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder, alpha_flag, pIccTransform, m_BlendType);\r
1612             if (!m_Stretcher.Start(&m_Composer, pSource, dest_height, dest_width, bitmap_clip, dib_flags)) {\r
1613                 return FALSE;\r
1614             }\r
1615             m_Status = 1;\r
1616             return TRUE;\r
1617         }\r
1618         m_Status = 2;\r
1619         m_pTransformer = FX_NEW CFX_ImageTransformer;\r
1620         if (!m_pTransformer) {\r
1621             return FALSE;\r
1622         }\r
1623         m_pTransformer->Start(pSource, &m_Matrix, dib_flags, &m_ClipBox);\r
1624         return TRUE;\r
1625     }\r
1626     int dest_width = image_rect.Width();\r
1627     if (m_Matrix.a < 0) {\r
1628         dest_width = -dest_width;\r
1629     }\r
1630     int dest_height = image_rect.Height();\r
1631     if (m_Matrix.d > 0) {\r
1632         dest_height = -dest_height;\r
1633     }\r
1634     if (dest_width == 0 || dest_height == 0) {\r
1635         return FALSE;\r
1636     }\r
1637     FX_RECT bitmap_clip = m_ClipBox;\r
1638     bitmap_clip.Offset(-image_rect.left, -image_rect.top);\r
1639     m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color,\r
1640                        m_ClipBox, FALSE, FALSE, FALSE, m_bRgbByteOrder, alpha_flag, pIccTransform, m_BlendType);\r
1641     m_Status = 1;\r
1642     ret = m_Stretcher.Start(&m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags);\r
1643     return ret;\r
1644 }\r
1645 FX_BOOL CFX_ImageRenderer::Continue(IFX_Pause* pPause)\r
1646 {\r
1647     if (m_Status == 1) {\r
1648         return m_Stretcher.Continue(pPause);\r
1649     } else if (m_Status == 2) {\r
1650         if (m_pTransformer->Continue(pPause)) {\r
1651             return TRUE;\r
1652         }\r
1653         CFX_DIBitmap* pBitmap = m_pTransformer->m_Storer.Detach();\r
1654         if (pBitmap == NULL) {\r
1655             return FALSE;\r
1656         }\r
1657         if (pBitmap->GetBuffer() == NULL) {\r
1658             delete pBitmap;\r
1659             return FALSE;\r
1660         }\r
1661         if (pBitmap->IsAlphaMask()) {\r
1662             if (m_BitmapAlpha != 255) {\r
1663                 if (m_AlphaFlag >> 8) {\r
1664                     m_AlphaFlag = (((FX_BYTE)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) | ((m_AlphaFlag >> 8) << 8));\r
1665                 } else {\r
1666                     m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);\r
1667                 }\r
1668             }\r
1669             m_pDevice->CompositeMask(m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop,\r
1670                                      pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, m_MaskColor,\r
1671                                      0, 0, m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_AlphaFlag, m_pIccTransform);\r
1672         } else {\r
1673             if (m_BitmapAlpha != 255) {\r
1674                 pBitmap->MultiplyAlpha(m_BitmapAlpha);\r
1675             }\r
1676             m_pDevice->CompositeBitmap(m_pTransformer->m_ResultLeft, m_pTransformer->m_ResultTop,\r
1677                                        pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap, 0, 0, m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_pIccTransform);\r
1678         }\r
1679         delete pBitmap;\r
1680         return FALSE;\r
1681     }\r
1682     return FALSE;\r
1683 }\r
1684 CFX_BitmapStorer::CFX_BitmapStorer()\r
1685 {\r
1686     m_pBitmap = NULL;\r
1687 }\r
1688 CFX_BitmapStorer::~CFX_BitmapStorer()\r
1689 {\r
1690     if (m_pBitmap) {\r
1691         delete m_pBitmap;\r
1692     }\r
1693 }\r
1694 CFX_DIBitmap* CFX_BitmapStorer::Detach()\r
1695 {\r
1696     CFX_DIBitmap* pBitmap = m_pBitmap;\r
1697     m_pBitmap = NULL;\r
1698     return pBitmap;\r
1699 }\r
1700 void CFX_BitmapStorer::Replace(CFX_DIBitmap* pBitmap)\r
1701 {\r
1702     if (m_pBitmap) {\r
1703         delete m_pBitmap;\r
1704     }\r
1705     m_pBitmap = pBitmap;\r
1706 }\r
1707 void CFX_BitmapStorer::ComposeScanline(int line, FX_LPCBYTE scanline, FX_LPCBYTE scan_extra_alpha)\r
1708 {\r
1709     FX_LPBYTE dest_buf = (FX_LPBYTE)m_pBitmap->GetScanline(line);\r
1710     FX_LPBYTE dest_alpha_buf = m_pBitmap->m_pAlphaMask ?\r
1711                                (FX_LPBYTE)m_pBitmap->m_pAlphaMask->GetScanline(line) : NULL;\r
1712     if (dest_buf) {\r
1713         FXSYS_memcpy32(dest_buf, scanline, m_pBitmap->GetPitch());\r
1714     }\r
1715     if (dest_alpha_buf) {\r
1716         FXSYS_memcpy32(dest_alpha_buf, scan_extra_alpha, m_pBitmap->m_pAlphaMask->GetPitch());\r
1717     }\r
1718 }\r
1719 FX_BOOL CFX_BitmapStorer::SetInfo(int width, int height, FXDIB_Format src_format, FX_DWORD* pSrcPalette)\r
1720 {\r
1721     m_pBitmap = FX_NEW CFX_DIBitmap;\r
1722     if (!m_pBitmap) {\r
1723         return FALSE;\r
1724     }\r
1725     if (!m_pBitmap->Create(width, height, src_format)) {\r
1726         delete m_pBitmap;\r
1727         m_pBitmap = NULL;\r
1728         return FALSE;\r
1729     }\r
1730     if (pSrcPalette) {\r
1731         m_pBitmap->CopyPalette(pSrcPalette);\r
1732     }\r
1733     return TRUE;\r
1734 }\r