diff options
author | caryclark <caryclark@google.com> | 2016-04-12 05:08:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-04-12 05:08:17 -0700 |
commit | f9924422a4cd1d1b6d2d4240c83b5c1082da3629 (patch) | |
tree | 94b978e3ee586645eccb6ad6c0d35d3ba7c808b1 /core/fpdfapi | |
parent | 822484b5f88d92dbcd567b1c2da38af1e720b56f (diff) | |
download | pdfium-f9924422a4cd1d1b6d2d4240c83b5c1082da3629.tar.xz |
flesh out gradient shaders
Using these webpages as guides
http://www.globelegislators.org/pdfjs/test/pdfs/alphatrans.pdf
http://www.antennahouse.com/antenna1/wp-content/uploads/2015/07/background-image-gradient-1.pdf
flesh out the gradient shaders to include the PostScript Type 0
sampling function and to include radial gradients. This CL makes
rendering these pages agree with Adobe Reader output.
Some of these examples use an Extend array to clip the gradient.
Skia does not currently support this natively, so construct the
clip manually for now.
Other PDF pages may construct gradients using alternate mechanisms
-- this code will continue to be refactored as those come to light.
In particular, this CL sets up the clip and matrix differently for
axial gradients and radial gradients -- while it makes sense to do
it one way only, I prefer to defer until I have more examples to
work with.
R=dsinclair@chromium.org,tsepez@chromium.org
Review URL: https://codereview.chromium.org/1870463002
Diffstat (limited to 'core/fpdfapi')
-rw-r--r-- | core/fpdfapi/fpdf_page/fpdf_page_func.cpp | 86 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_page/pageint.h | 28 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp | 4 |
3 files changed, 63 insertions, 55 deletions
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp index b00ab73af1..31faf6a2d7 100644 --- a/core/fpdfapi/fpdf_page/fpdf_page_func.cpp +++ b/core/fpdfapi/fpdf_page/fpdf_page_func.cpp @@ -491,28 +491,40 @@ static uint32_t _GetBits32(const uint8_t* pData, int bitpos, int nbits) { } return result; } -typedef struct { - FX_FLOAT encode_max, encode_min; - int sizes; -} SampleEncodeInfo; -typedef struct { FX_FLOAT decode_max, decode_min; } SampleDecodeInfo; -class CPDF_SampledFunc : public CPDF_Function { +class CPDF_PSFunc : public CPDF_Function { public: - CPDF_SampledFunc(); - ~CPDF_SampledFunc() override; - + CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} // CPDF_Function FX_BOOL v_Init(CPDF_Object* pObj) override; FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - SampleEncodeInfo* m_pEncodeInfo; - SampleDecodeInfo* m_pDecodeInfo; - uint32_t m_nBitsPerSample; - uint32_t m_SampleMax; - CPDF_StreamAcc* m_pSampleStream; + private: + CPDF_PSEngine m_PS; }; +FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) { + CPDF_StreamAcc acc; + acc.LoadAllData(pObj->AsStream(), FALSE); + return m_PS.Parse(reinterpret_cast<const FX_CHAR*>(acc.GetData()), + acc.GetSize()); +} + +FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { + CPDF_PSEngine& PS = const_cast<CPDF_PSEngine&>(m_PS); + PS.Reset(); + for (uint32_t i = 0; i < m_nInputs; i++) + PS.Push(inputs[i]); + PS.Execute(); + if (PS.GetStackSize() < m_nOutputs) + return FALSE; + for (uint32_t i = 0; i < m_nOutputs; i++) + results[m_nOutputs - i - 1] = PS.Pop(); + return TRUE; +} + +} // namespace + CPDF_SampledFunc::CPDF_SampledFunc() : CPDF_Function(Type::kType0Sampled) { m_pSampleStream = NULL; m_pEncodeInfo = NULL; @@ -524,6 +536,7 @@ CPDF_SampledFunc::~CPDF_SampledFunc() { FX_Free(m_pEncodeInfo); FX_Free(m_pDecodeInfo); } + FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { CPDF_Stream* pStream = pObj->AsStream(); if (!pStream) @@ -579,13 +592,14 @@ FX_BOOL CPDF_SampledFunc::v_Init(CPDF_Object* pObj) { } return TRUE; } + FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { int pos = 0; CFX_FixedBufGrow<FX_FLOAT, 16> encoded_input_buf(m_nInputs); FX_FLOAT* encoded_input = encoded_input_buf; - CFX_FixedBufGrow<int, 32> int_buf(m_nInputs * 2); - int* index = int_buf; - int* blocksize = index + m_nInputs; + CFX_FixedBufGrow<uint32_t, 32> int_buf(m_nInputs * 2); + uint32_t* index = int_buf; + uint32_t* blocksize = index + m_nInputs; for (uint32_t i = 0; i < m_nInputs; i++) { if (i == 0) blocksize[i] = 1; @@ -594,11 +608,8 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { encoded_input[i] = PDF_Interpolate( inputs[i], m_pDomains[i * 2], m_pDomains[i * 2 + 1], m_pEncodeInfo[i].encode_min, m_pEncodeInfo[i].encode_max); - index[i] = (int)encoded_input[i]; - if (index[i] < 0) - index[i] = 0; - else if (index[i] > m_pEncodeInfo[i].sizes - 1) - index[i] = m_pEncodeInfo[i].sizes - 1; + index[i] = std::min((uint32_t)std::max(0.f, encoded_input[i]), + m_pEncodeInfo[i].sizes - 1); pos += index[i] * blocksize[i]; } FX_SAFE_INT32 bits_to_output = m_nOutputs; @@ -650,37 +661,6 @@ FX_BOOL CPDF_SampledFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { return TRUE; } -class CPDF_PSFunc : public CPDF_Function { - public: - // CPDF_Function - CPDF_PSFunc() : CPDF_Function(Type::kType4PostScript) {} - FX_BOOL v_Init(CPDF_Object* pObj) override; - FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; - - CPDF_PSEngine m_PS; -}; - -FX_BOOL CPDF_PSFunc::v_Init(CPDF_Object* pObj) { - CPDF_Stream* pStream = pObj->AsStream(); - CPDF_StreamAcc acc; - acc.LoadAllData(pStream, FALSE); - return m_PS.Parse((const FX_CHAR*)acc.GetData(), acc.GetSize()); -} -FX_BOOL CPDF_PSFunc::v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const { - CPDF_PSEngine& PS = (CPDF_PSEngine&)m_PS; - PS.Reset(); - for (uint32_t i = 0; i < m_nInputs; i++) - PS.Push(inputs[i]); - PS.Execute(); - if (PS.GetStackSize() < m_nOutputs) - return FALSE; - for (uint32_t i = 0; i < m_nOutputs; i++) - results[m_nOutputs - i - 1] = PS.Pop(); - return TRUE; -} - -} // namespace - CPDF_ExpIntFunc::CPDF_ExpIntFunc() : CPDF_Function(Type::kType2ExpotentialInterpolation) { m_pBeginValues = NULL; diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h index e6496cfd20..98a05d5495 100644 --- a/core/fpdfapi/fpdf_page/pageint.h +++ b/core/fpdfapi/fpdf_page/pageint.h @@ -393,6 +393,7 @@ class CPDF_Function { uint32_t CountInputs() const { return m_nInputs; } uint32_t CountOutputs() const { return m_nOutputs; } FX_FLOAT GetDomain(int i) const { return m_pDomains[i]; } + FX_FLOAT GetRange(int i) const { return m_pRanges[i]; } Type GetType() const { return m_Type; } protected: @@ -423,6 +424,33 @@ class CPDF_ExpIntFunc : public CPDF_Function { FX_FLOAT* m_pEndValues; }; +class CPDF_SampledFunc : public CPDF_Function { + public: + struct SampleEncodeInfo { + FX_FLOAT encode_max; + FX_FLOAT encode_min; + uint32_t sizes; + }; + + struct SampleDecodeInfo { + FX_FLOAT decode_max; + FX_FLOAT decode_min; + }; + + CPDF_SampledFunc(); + ~CPDF_SampledFunc() override; + + // CPDF_Function + FX_BOOL v_Init(CPDF_Object* pObj) override; + FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override; + + SampleEncodeInfo* m_pEncodeInfo; + SampleDecodeInfo* m_pDecodeInfo; + uint32_t m_nBitsPerSample; + uint32_t m_SampleMax; + CPDF_StreamAcc* m_pSampleStream; +}; + class CPDF_StitchFunc : public CPDF_Function { public: CPDF_StitchFunc(); diff --git a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp index 3f98279dbf..48f9f5d98a 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp @@ -855,8 +855,8 @@ void CPDF_RenderStatus::DrawShading(CPDF_ShadingPattern* pPattern, clip_rect.Intersect(rect.GetOutterRect()); } if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SHADING && - m_pDevice->GetDeviceDriver()->DrawShading(pPattern, pMatrix, alpha, - bAlphaMode)) { + m_pDevice->GetDeviceDriver()->DrawShading(pPattern, pMatrix, clip_rect, + alpha, bAlphaMode)) { return; } CPDF_DeviceBuffer buffer; |