Chromium Code Reviews| 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 |