diff options
Diffstat (limited to 'core/fxge/win32/cfx_psrenderer.cpp')
-rw-r--r-- | core/fxge/win32/cfx_psrenderer.cpp | 274 |
1 files changed, 141 insertions, 133 deletions
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index 46af33710c..ba027ba6dc 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp @@ -19,6 +19,60 @@ #include "core/fxge/win32/cpsoutput.h" #include "third_party/base/ptr_util.h" +namespace { + +void FaxCompressData(uint8_t* src_buf, + int width, + int height, + std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, + uint32_t* dest_size) { + if (width * height > 128) { + CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8, + dest_buf, dest_size); + FX_Free(src_buf); + } else { + dest_buf->reset(src_buf); + *dest_size = (width + 7) / 8 * height; + } +} + +void PSCompressData(int PSLevel, + uint8_t* src_buf, + uint32_t src_size, + uint8_t** output_buf, + uint32_t* output_size, + const char** filter) { + *output_buf = src_buf; + *output_size = src_size; + *filter = ""; + if (src_size < 1024) + return; + + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + uint8_t* dest_buf = nullptr; + uint32_t dest_size = src_size; + if (PSLevel >= 3) { + if (pEncoders && pEncoders->GetFlateModule()->Encode( + src_buf, src_size, &dest_buf, &dest_size)) { + *filter = "/FlateDecode filter "; + } + } else { + if (pEncoders && pEncoders->GetBasicModule()->RunLengthEncode( + src_buf, src_size, &dest_buf, &dest_size)) { + *filter = "/RunLengthDecode filter "; + } + } + if (dest_size < src_size) { + *output_buf = dest_buf; + *output_size = dest_size; + } else { + *filter = nullptr; + FX_Free(dest_buf); + } +} + +} // namespace + struct PSGlyph { CFX_Font* m_pFont; uint32_t m_GlyphIndex; @@ -32,33 +86,32 @@ class CPSFont { int m_nGlyphs; }; -CFX_PSRenderer::CFX_PSRenderer() { - m_pOutput = nullptr; - m_bColorSet = m_bGraphStateSet = false; - m_bInited = false; -} +CFX_PSRenderer::CFX_PSRenderer() + : m_pStream(nullptr), + m_bGraphStateSet(false), + m_bColorSet(false), + m_bInited(false) {} CFX_PSRenderer::~CFX_PSRenderer() {} -#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof(str) - 1) - -void CFX_PSRenderer::Init(CPSOutput* pOutput, +void CFX_PSRenderer::Init(const CFX_RetainPtr<IFX_WriteStream>& pStream, int pslevel, int width, int height, bool bCmykOutput) { m_PSLevel = pslevel; - m_pOutput = pOutput; - m_ClipBox.left = m_ClipBox.top = 0; + m_pStream = pStream; + m_ClipBox.left = 0; + m_ClipBox.top = 0; m_ClipBox.right = width; m_ClipBox.bottom = height; m_bCmykOutput = bCmykOutput; } bool CFX_PSRenderer::StartRendering() { - if (m_bInited) { + if (m_bInited) return true; - } + static const char init_str[] = "\nsave\n/im/initmatrix load def\n" "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load " @@ -73,30 +126,30 @@ bool CFX_PSRenderer::StartRendering() { "load def\n" "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load " "def/sm/setmatrix load def\n"; - OUTPUT_PS(init_str); + m_pStream->WriteString(init_str); m_bInited = true; return true; } void CFX_PSRenderer::EndRendering() { - if (m_bInited) { - OUTPUT_PS("\nrestore\n"); - m_bInited = false; - } + if (!m_bInited) + return; + + m_pStream->WriteString("\nrestore\n"); + m_bInited = false; } void CFX_PSRenderer::SaveState() { StartRendering(); - OUTPUT_PS("q\n"); + m_pStream->WriteString("q\n"); m_ClipBoxStack.push_back(m_ClipBox); } void CFX_PSRenderer::RestoreState(bool bKeepSaved) { StartRendering(); + m_pStream->WriteString("Q\n"); if (bKeepSaved) - OUTPUT_PS("Q\nq\n"); - else - OUTPUT_PS("Q\n"); + m_pStream->WriteString("q\n"); m_bColorSet = false; m_bGraphStateSet = false; @@ -148,7 +201,7 @@ void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, } } } - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, @@ -164,11 +217,11 @@ void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, m_ClipBox.right = static_cast<int>(rect.left + rect.right); m_ClipBox.top = static_cast<int>(rect.top + rect.bottom); m_ClipBox.bottom = static_cast<int>(rect.bottom); - if ((fill_mode & 3) == FXFILL_WINDING) { - OUTPUT_PS("W n\n"); - } else { - OUTPUT_PS("W* n\n"); - } + + m_pStream->WriteString("W"); + if ((fill_mode & 3) != FXFILL_WINDING) + m_pStream->WriteString("*"); + m_pStream->WriteString(" n\n"); } void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData, @@ -181,18 +234,19 @@ void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData, buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " " << pObject2Device->c << " " << pObject2Device->d << " " << pObject2Device->e << " " << pObject2Device->f << "]cm "; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } + OutputPath(pPathData, nullptr); CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); pObject2Device->TransformRect(rect); m_ClipBox.Intersect(rect.GetOuterRect()); - if (pObject2Device) { - OUTPUT_PS("strokepath W n sm\n"); - } else { - OUTPUT_PS("strokepath W n\n"); - } + + m_pStream->WriteString("strokepath W n"); + if (pObject2Device) + m_pStream->WriteString(" sm"); + m_pStream->WriteString("\n"); } bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, @@ -204,15 +258,13 @@ bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, StartRendering(); int fill_alpha = FXARGB_A(fill_color); int stroke_alpha = FXARGB_A(stroke_color); - if (fill_alpha && fill_alpha < 255) { + if (fill_alpha && fill_alpha < 255) return false; - } - if (stroke_alpha && stroke_alpha < 255) { + if (stroke_alpha && stroke_alpha < 255) return false; - } - if (fill_alpha == 0 && stroke_alpha == 0) { + if (fill_alpha == 0 && stroke_alpha == 0) return false; - } + if (stroke_alpha) { SetGraphState(pGraphState); if (pObject2Device) { @@ -220,35 +272,34 @@ bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " " << pObject2Device->c << " " << pObject2Device->d << " " << pObject2Device->e << " " << pObject2Device->f << "]cm "; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } } + OutputPath(pPathData, stroke_alpha ? nullptr : pObject2Device); if (fill_mode && fill_alpha) { SetColor(fill_color); if ((fill_mode & 3) == FXFILL_WINDING) { - if (stroke_alpha) { - OUTPUT_PS("q f Q "); - } else { - OUTPUT_PS("f"); - } + if (stroke_alpha) + m_pStream->WriteString("q f Q "); + else + m_pStream->WriteString("f"); } else if ((fill_mode & 3) == FXFILL_ALTERNATE) { - if (stroke_alpha) { - OUTPUT_PS("q F Q "); - } else { - OUTPUT_PS("F"); - } + if (stroke_alpha) + m_pStream->WriteString("q F Q "); + else + m_pStream->WriteString("F"); } } + if (stroke_alpha) { SetColor(stroke_color); - if (pObject2Device) { - OUTPUT_PS("s sm"); - } else { - OUTPUT_PS("s"); - } + m_pStream->WriteString("s"); + if (pObject2Device) + m_pStream->WriteString(" sm"); } - OUTPUT_PS("\n"); + + m_pStream->WriteString("\n"); return true; } @@ -263,9 +314,9 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, sizeof(float) * m_CurGraphState.m_DashCount)) { buf << "["; - for (int i = 0; i < pGraphState->m_DashCount; ++i) { + for (int i = 0; i < pGraphState->m_DashCount; ++i) buf << pGraphState->m_DashArray[i] << " "; - } + buf << "]" << pGraphState->m_DashPhase << " d\n"; } if (!m_bGraphStateSet || @@ -282,61 +333,8 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { } m_CurGraphState.Copy(*pGraphState); m_bGraphStateSet = true; - if (buf.GetSize()) { - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); - } -} - -static void FaxCompressData(uint8_t* src_buf, - int width, - int height, - std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, - uint32_t* dest_size) { - if (width * height > 128) { - CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8, - dest_buf, dest_size); - FX_Free(src_buf); - } else { - dest_buf->reset(src_buf); - *dest_size = (width + 7) / 8 * height; - } -} - -static void PSCompressData(int PSLevel, - uint8_t* src_buf, - uint32_t src_size, - uint8_t** output_buf, - uint32_t* output_size, - const char** filter) { - *output_buf = src_buf; - *output_size = src_size; - *filter = ""; - if (src_size < 1024) { - return; - } - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - uint8_t* dest_buf = nullptr; - uint32_t dest_size = src_size; - if (PSLevel >= 3) { - if (pEncoders && - pEncoders->GetFlateModule()->Encode(src_buf, src_size, &dest_buf, - &dest_size)) { - *filter = "/FlateDecode filter "; - } - } else { - if (pEncoders && - pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size, - &dest_buf, &dest_size)) { - *filter = "/RunLengthDecode filter "; - } - } - if (dest_size < src_size) { - *output_buf = dest_buf; - *output_size = dest_size; - } else { - *filter = nullptr; - FX_Free(dest_buf); - } + if (buf.GetSize()) + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } bool CFX_PSRenderer::SetDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, @@ -372,20 +370,23 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, (pMatrix->c == 0 && pMatrix->d == 0)) { return true; } - if (pSource->HasAlpha()) { + if (pSource->HasAlpha()) return false; - } + int alpha = FXARGB_A(color); if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1)) return false; - OUTPUT_PS("q\n"); + m_pStream->WriteString("q\n"); + CFX_ByteTextBuf buf; buf << "[" << pMatrix->a << " " << pMatrix->b << " " << pMatrix->c << " " << pMatrix->d << " " << pMatrix->e << " " << pMatrix->f << "]cm "; + int width = pSource->GetWidth(); int height = pSource->GetHeight(); buf << width << " " << height; + if (pSource->GetBPP() == 1 && !pSource->GetPalette()) { int pitch = (width + 7) / 8; uint32_t src_size = height * pitch; @@ -394,6 +395,7 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, const uint8_t* src_scan = pSource->GetScanline(row); memcpy(src_buf + row * pitch, src_scan, pitch); } + std::unique_ptr<uint8_t, FxFreeDeleter> output_buf; uint32_t output_size; FaxCompressData(src_buf, width, height, &output_buf, &output_size); @@ -406,16 +408,17 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, } buf << width << " 0 0 -" << height << " 0 " << height << "]currentfile/ASCII85Decode filter "; + if (output_buf.get() != src_buf) { buf << "<</K -1/EndOfBlock false/Columns " << width << "/Rows " << height << ">>/CCITTFaxDecode filter "; } - if (pSource->IsAlphaMask()) { + if (pSource->IsAlphaMask()) buf << "iM\n"; - } else { + else buf << "false 1 colorimage\n"; - } - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); WritePSBinary(output_buf.get(), output_size); output_buf.release(); } else { @@ -445,9 +448,10 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, break; } if (!pConverted) { - OUTPUT_PS("\nQ\n"); + m_pStream->WriteString("\nQ\n"); return false; } + int bpp = pConverted->GetBPP() / 8; uint8_t* output_buf = nullptr; FX_STRSIZE output_size = 0; @@ -478,25 +482,26 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource, uint32_t compressed_size; PSCompressData(m_PSLevel, output_buf, output_size, &compressed_buf, &compressed_size, &filter); - if (output_buf != compressed_buf) { + if (output_buf != compressed_buf) FX_Free(output_buf); - } + output_buf = compressed_buf; output_size = compressed_size; } buf << " 8["; buf << width << " 0 0 -" << height << " 0 " << height << "]"; buf << "currentfile/ASCII85Decode filter "; - if (filter) { + if (filter) buf << filter; - } + buf << "false " << bpp; buf << " colorimage\n"; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); + WritePSBinary(output_buf, output_size); FX_Free(output_buf); } - OUTPUT_PS("\nQ\n"); + m_pStream->WriteString("\nQ\n"); return true; } @@ -517,7 +522,7 @@ void CFX_PSRenderer::SetColor(uint32_t color) { m_bColorSet = true; m_LastColor = color; } - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } } @@ -548,6 +553,7 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, } ++i; } + if (m_PSFontList.empty() || m_PSFontList.back()->m_nGlyphs == 256) { m_PSFontList.push_back(pdfium::MakeUnique<CPSFont>()); m_PSFontList.back()->m_nGlyphs = 0; @@ -563,9 +569,10 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, "currentdict end\n"; buf << "/X" << static_cast<uint32_t>(m_PSFontList.size() - 1) << " exch definefont pop\n"; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); buf.Clear(); } + *ps_fontnum = m_PSFontList.size() - 1; CPSFont* pPSFont = m_PSFontList[*ps_fontnum].get(); int glyphindex = pPSFont->m_nGlyphs; @@ -624,7 +631,7 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, buf << "f}bind def end\n"; buf << "/X" << *ps_fontnum << " Ff/Encoding get " << glyphindex << "/" << glyphindex << " put\n"; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); } bool CFX_PSRenderer::DrawText(int nChars, @@ -642,6 +649,7 @@ bool CFX_PSRenderer::DrawText(int nChars, (pObject2Device->c == 0 && pObject2Device->d == 0)) { return true; } + SetColor(color); CFX_ByteTextBuf buf; buf << "q[" << pObject2Device->a << " " << pObject2Device->b << " " @@ -665,7 +673,7 @@ bool CFX_PSRenderer::DrawText(int nChars, buf << hex.AsStringC() << "Tj\n"; } buf << "Q\n"; - m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize()); + m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize()); pCache->ReleaseCachedFace(pFont); return true; } @@ -677,9 +685,9 @@ void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) { if (pEncoders && pEncoders->GetBasicModule()->A85Encode(data, len, &dest_buf, &dest_size)) { - m_pOutput->OutputPS((const char*)dest_buf, dest_size); + m_pStream->WriteBlock(dest_buf, dest_size); FX_Free(dest_buf); } else { - m_pOutput->OutputPS((const char*)data, len); + m_pStream->WriteBlock(data, len); } } |