OLD | NEW |
---|---|
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include <limits.h> | 7 #include <limits.h> |
8 | 8 |
9 #include "core/fxge/dib/dib_int.h" | 9 #include "core/fxge/dib/dib_int.h" |
10 #include "core/fxge/include/fx_dib.h" | 10 #include "core/fxge/include/fx_dib.h" |
11 #include "core/fxge/include/fx_ge.h" | 11 #include "core/fxge/include/fx_ge.h" |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 bool SourceSizeWithinLimit(int width, int height) { | |
16 const int kMaxProgressiveStretchPixels = 1000000; | |
Tom Sepez
2016/05/12 00:03:08
Ok for now, but seems kinda small. A megapixel?
Lei Zhang
2016/05/12 01:17:13
I have no idea why it's so small.
| |
17 return !height || width < kMaxProgressiveStretchPixels / height; | |
18 } | |
19 | |
15 FXDIB_Format GetStretchedFormat(const CFX_DIBSource& src) { | 20 FXDIB_Format GetStretchedFormat(const CFX_DIBSource& src) { |
16 FXDIB_Format format = src.GetFormat(); | 21 FXDIB_Format format = src.GetFormat(); |
17 if (format == FXDIB_1bppMask) | 22 if (format == FXDIB_1bppMask) |
18 return FXDIB_8bppMask; | 23 return FXDIB_8bppMask; |
19 if (format == FXDIB_1bppRgb) | 24 if (format == FXDIB_1bppRgb) |
20 return FXDIB_8bppRgb; | 25 return FXDIB_8bppRgb; |
21 if (format == FXDIB_8bppRgb && src.GetPalette()) | 26 if (format == FXDIB_8bppRgb && src.GetPalette()) |
22 return FXDIB_Rgb; | 27 return FXDIB_Rgb; |
23 return format; | 28 return format; |
24 } | 29 } |
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
763 } | 768 } |
764 } | 769 } |
765 break; | 770 break; |
766 } | 771 } |
767 } | 772 } |
768 m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline, | 773 m_pDestBitmap->ComposeScanline(row - m_DestClip.top, m_pDestScanline, |
769 m_pDestMaskScanline); | 774 m_pDestMaskScanline); |
770 } | 775 } |
771 } | 776 } |
772 | 777 |
773 CFX_ImageStretcher::CFX_ImageStretcher() | 778 CFX_ImageStretcher::CFX_ImageStretcher(IFX_ScanlineComposer* pDest, |
774 : m_pStretchEngine(nullptr), | 779 const CFX_DIBSource* pSource, |
780 int dest_width, | |
781 int dest_height, | |
782 const FX_RECT& bitmap_rect, | |
783 uint32_t flags) | |
784 : m_pDest(pDest), | |
785 m_pSource(pSource), | |
775 m_pScanline(nullptr), | 786 m_pScanline(nullptr), |
776 m_pMaskScanline(nullptr) {} | 787 m_pMaskScanline(nullptr), |
788 m_Flags(flags), | |
789 m_bFlipX(FALSE), | |
790 m_bFlipY(FALSE), | |
791 m_DestWidth(dest_width), | |
792 m_DestHeight(dest_height), | |
793 m_ClipRect(bitmap_rect), | |
794 m_DestFormat(GetStretchedFormat(*pSource)), | |
795 m_DestBPP(m_DestFormat & 0xff), | |
796 m_LineIndex(0) {} | |
777 | 797 |
778 CFX_ImageStretcher::~CFX_ImageStretcher() { | 798 CFX_ImageStretcher::~CFX_ImageStretcher() { |
779 FX_Free(m_pScanline); | 799 FX_Free(m_pScanline); |
Tom Sepez
2016/05/12 00:03:08
can these be unique_ptr<..., FreeDeleter> ?
Lei Zhang
2016/05/12 01:17:13
Done.
| |
780 delete m_pStretchEngine; | |
781 FX_Free(m_pMaskScanline); | 800 FX_Free(m_pMaskScanline); |
782 } | 801 } |
783 | 802 |
784 FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest, | 803 FX_BOOL CFX_ImageStretcher::Start() { |
785 const CFX_DIBSource* pSource, | 804 if (m_DestWidth == 0 || m_DestHeight == 0) |
786 int dest_width, | |
787 int dest_height, | |
788 const FX_RECT& rect, | |
789 uint32_t flags) { | |
790 if (dest_width == 0 || dest_height == 0) | |
791 return FALSE; | 805 return FALSE; |
792 | 806 |
793 m_DestFormat = GetStretchedFormat(*pSource); | 807 if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) { |
794 m_DestBPP = m_DestFormat & 0xff; | |
795 m_pDest = pDest; | |
796 m_pSource = pSource; | |
797 m_DestWidth = dest_width; | |
798 m_DestHeight = dest_height; | |
799 m_ClipRect = rect; | |
800 m_Flags = flags; | |
801 | |
802 if (pSource->GetFormat() == FXDIB_1bppRgb && pSource->GetPalette()) { | |
803 FX_ARGB pal[256]; | 808 FX_ARGB pal[256]; |
804 int a0, r0, g0, b0, a1, r1, g1, b1; | 809 int a0, r0, g0, b0, a1, r1, g1, b1; |
805 ArgbDecode(pSource->GetPaletteEntry(0), a0, r0, g0, b0); | 810 ArgbDecode(m_pSource->GetPaletteEntry(0), a0, r0, g0, b0); |
806 ArgbDecode(pSource->GetPaletteEntry(1), a1, r1, g1, b1); | 811 ArgbDecode(m_pSource->GetPaletteEntry(1), a1, r1, g1, b1); |
807 for (int i = 0; i < 256; i++) { | 812 for (int i = 0; i < 256; i++) { |
808 int a = a0 + (a1 - a0) * i / 255; | 813 int a = a0 + (a1 - a0) * i / 255; |
809 int r = r0 + (r1 - r0) * i / 255; | 814 int r = r0 + (r1 - r0) * i / 255; |
810 int g = g0 + (g1 - g0) * i / 255; | 815 int g = g0 + (g1 - g0) * i / 255; |
811 int b = b0 + (b1 - b0) * i / 255; | 816 int b = b0 + (b1 - b0) * i / 255; |
812 pal[i] = ArgbEncode(a, r, g, b); | 817 pal[i] = ArgbEncode(a, r, g, b); |
813 } | 818 } |
814 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { | 819 if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, |
820 pal)) { | |
815 return FALSE; | 821 return FALSE; |
816 } | 822 } |
817 } else if (pSource->GetFormat() == FXDIB_1bppCmyk && pSource->GetPalette()) { | 823 } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk && |
824 m_pSource->GetPalette()) { | |
818 FX_CMYK pal[256]; | 825 FX_CMYK pal[256]; |
819 int c0, m0, y0, k0, c1, m1, y1, k1; | 826 int c0, m0, y0, k0, c1, m1, y1, k1; |
820 CmykDecode(pSource->GetPaletteEntry(0), c0, m0, y0, k0); | 827 CmykDecode(m_pSource->GetPaletteEntry(0), c0, m0, y0, k0); |
821 CmykDecode(pSource->GetPaletteEntry(1), c1, m1, y1, k1); | 828 CmykDecode(m_pSource->GetPaletteEntry(1), c1, m1, y1, k1); |
822 for (int i = 0; i < 256; i++) { | 829 for (int i = 0; i < 256; i++) { |
823 int c = c0 + (c1 - c0) * i / 255; | 830 int c = c0 + (c1 - c0) * i / 255; |
824 int m = m0 + (m1 - m0) * i / 255; | 831 int m = m0 + (m1 - m0) * i / 255; |
825 int y = y0 + (y1 - y0) * i / 255; | 832 int y = y0 + (y1 - y0) * i / 255; |
826 int k = k0 + (k1 - k0) * i / 255; | 833 int k = k0 + (k1 - k0) * i / 255; |
827 pal[i] = CmykEncode(c, m, y, k); | 834 pal[i] = CmykEncode(c, m, y, k); |
828 } | 835 } |
829 if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) { | 836 if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat, |
837 pal)) { | |
830 return FALSE; | 838 return FALSE; |
831 } | 839 } |
832 } else if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, NULL)) { | 840 } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), |
841 m_DestFormat, nullptr)) { | |
833 return FALSE; | 842 return FALSE; |
834 } | 843 } |
835 | 844 |
836 if (flags & FXDIB_DOWNSAMPLE) | 845 if (m_Flags & FXDIB_DOWNSAMPLE) |
837 return StartQuickStretch(); | 846 return StartQuickStretch(); |
838 return StartStretch(); | 847 return StartStretch(); |
839 } | 848 } |
840 | 849 |
841 FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) { | 850 FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) { |
842 if (m_Flags & FXDIB_DOWNSAMPLE) | 851 if (m_Flags & FXDIB_DOWNSAMPLE) |
843 return ContinueQuickStretch(pPause); | 852 return ContinueQuickStretch(pPause); |
844 return ContinueStretch(pPause); | 853 return ContinueStretch(pPause); |
845 } | 854 } |
846 | 855 |
847 #define MAX_PROGRESSIVE_STRETCH_PIXELS 1000000 | |
848 FX_BOOL CFX_ImageStretcher::StartStretch() { | 856 FX_BOOL CFX_ImageStretcher::StartStretch() { |
849 m_pStretchEngine = | 857 m_pStretchEngine.reset(new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth, |
850 new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth, m_DestHeight, | 858 m_DestHeight, m_ClipRect, m_pSource, |
851 m_ClipRect, m_pSource, m_Flags); | 859 m_Flags)); |
852 m_pStretchEngine->StartStretchHorz(); | 860 m_pStretchEngine->StartStretchHorz(); |
853 if (m_pSource->GetWidth() * m_pSource->GetHeight() < | 861 if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { |
854 MAX_PROGRESSIVE_STRETCH_PIXELS) { | 862 m_pStretchEngine->Continue(nullptr); |
855 m_pStretchEngine->Continue(NULL); | |
856 return FALSE; | 863 return FALSE; |
857 } | 864 } |
858 return TRUE; | 865 return TRUE; |
859 } | 866 } |
867 | |
860 FX_BOOL CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) { | 868 FX_BOOL CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) { |
861 return m_pStretchEngine && m_pStretchEngine->Continue(pPause); | 869 return m_pStretchEngine && m_pStretchEngine->Continue(pPause); |
862 } | 870 } |
871 | |
863 FX_BOOL CFX_ImageStretcher::StartQuickStretch() { | 872 FX_BOOL CFX_ImageStretcher::StartQuickStretch() { |
864 m_bFlipX = FALSE; | |
865 m_bFlipY = FALSE; | |
866 if (m_DestWidth < 0) { | 873 if (m_DestWidth < 0) { |
867 m_bFlipX = TRUE; | 874 m_bFlipX = TRUE; |
868 m_DestWidth = -m_DestWidth; | 875 m_DestWidth = -m_DestWidth; |
869 } | 876 } |
870 if (m_DestHeight < 0) { | 877 if (m_DestHeight < 0) { |
871 m_bFlipY = TRUE; | 878 m_bFlipY = TRUE; |
872 m_DestHeight = -m_DestHeight; | 879 m_DestHeight = -m_DestHeight; |
873 } | 880 } |
874 m_LineIndex = 0; | |
875 uint32_t size = m_ClipRect.Width(); | 881 uint32_t size = m_ClipRect.Width(); |
876 if (size && m_DestBPP > (int)(INT_MAX / size)) { | 882 if (size && m_DestBPP > (int)(INT_MAX / size)) { |
877 return FALSE; | 883 return FALSE; |
878 } | 884 } |
879 size *= m_DestBPP; | 885 size *= m_DestBPP; |
880 m_pScanline = FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4); | 886 m_pScanline = FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4); |
881 if (m_pSource->m_pAlphaMask) { | 887 if (m_pSource->m_pAlphaMask) |
882 m_pMaskScanline = FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4); | 888 m_pMaskScanline = FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4); |
883 } | 889 |
884 if (m_pSource->GetWidth() * m_pSource->GetHeight() < | 890 if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { |
885 MAX_PROGRESSIVE_STRETCH_PIXELS) { | 891 ContinueQuickStretch(nullptr); |
886 ContinueQuickStretch(NULL); | |
887 return FALSE; | 892 return FALSE; |
888 } | 893 } |
889 return TRUE; | 894 return TRUE; |
890 } | 895 } |
896 | |
891 FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) { | 897 FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) { |
892 if (!m_pScanline) { | 898 if (!m_pScanline) { |
893 return FALSE; | 899 return FALSE; |
894 } | 900 } |
895 int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height(); | 901 int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height(); |
896 int src_height = m_pSource->GetHeight(); | 902 int src_height = m_pSource->GetHeight(); |
897 for (; m_LineIndex < result_height; m_LineIndex++) { | 903 for (; m_LineIndex < result_height; m_LineIndex++) { |
898 int dest_y, src_y; | 904 int dest_y, src_y; |
899 if (m_bFlipY) { | 905 if (m_bFlipY) { |
900 dest_y = result_height - m_LineIndex - 1; | 906 dest_y = result_height - m_LineIndex - 1; |
(...skipping 16 matching lines...) Expand all Loading... | |
917 m_bFlipX, m_ClipRect.left, result_width); | 923 m_bFlipX, m_ClipRect.left, result_width); |
918 if (m_pMaskScanline) { | 924 if (m_pMaskScanline) { |
919 m_pSource->m_pAlphaMask->DownSampleScanline( | 925 m_pSource->m_pAlphaMask->DownSampleScanline( |
920 src_y, m_pMaskScanline, 1, m_DestWidth, m_bFlipX, m_ClipRect.left, | 926 src_y, m_pMaskScanline, 1, m_DestWidth, m_bFlipX, m_ClipRect.left, |
921 result_width); | 927 result_width); |
922 } | 928 } |
923 m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline); | 929 m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline); |
924 } | 930 } |
925 return FALSE; | 931 return FALSE; |
926 } | 932 } |
OLD | NEW |