/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * */ #include #include #include #include // ----- Implementation of PrinterBmp by means of SalBitmap/BitmapBuffer --------------- namespace { class SalPrinterBmp : public psp::PrinterBmp { private: BitmapBuffer* mpBmpBuffer; FncGetPixel mpFncGetPixel; Scanline mpScanAccess; sal_PtrDiff mnScanOffset; public: explicit SalPrinterBmp(BitmapBuffer* pBitmap); virtual sal_uInt32 GetPaletteColor(sal_uInt32 nIdx) const override; virtual sal_uInt32 GetPaletteEntryCount() const override; virtual sal_uInt32 GetPixelRGB(sal_uInt32 nRow, sal_uInt32 nColumn) const override; virtual sal_uInt8 GetPixelGray(sal_uInt32 nRow, sal_uInt32 nColumn) const override; virtual sal_uInt8 GetPixelIdx(sal_uInt32 nRow, sal_uInt32 nColumn) const override; virtual sal_uInt32 GetDepth() const override; }; } SalPrinterBmp::SalPrinterBmp(BitmapBuffer* pBuffer) : mpBmpBuffer(pBuffer) { assert(mpBmpBuffer && "SalPrinterBmp::SalPrinterBmp () can't acquire Bitmap"); // calibrate scanline buffer if (mpBmpBuffer->mnFormat & ScanlineFormat::TopDown) { mpScanAccess = mpBmpBuffer->mpBits; mnScanOffset = mpBmpBuffer->mnScanlineSize; } else { mpScanAccess = mpBmpBuffer->mpBits + (mpBmpBuffer->mnHeight - 1) * mpBmpBuffer->mnScanlineSize; mnScanOffset = -mpBmpBuffer->mnScanlineSize; } // request read access to the pixels mpFncGetPixel = BitmapReadAccess::GetPixelFunction(mpBmpBuffer->mnFormat); } sal_uInt32 SalPrinterBmp::GetDepth() const { sal_uInt32 nDepth; switch (mpBmpBuffer->mnBitCount) { case 1: nDepth = 1; break; case 4: case 8: nDepth = 8; break; case 24: case 32: nDepth = 24; break; default: nDepth = 1; assert(false && "Error: unsupported bitmap depth in SalPrinterBmp::GetDepth()"); break; } return nDepth; } sal_uInt32 SalPrinterBmp::GetPaletteEntryCount() const { return mpBmpBuffer->maPalette.GetEntryCount(); } sal_uInt32 SalPrinterBmp::GetPaletteColor(sal_uInt32 nIdx) const { BitmapColor aColor(mpBmpBuffer->maPalette[nIdx]); return ((aColor.GetBlue()) & 0x000000ff) | ((aColor.GetGreen() << 8) & 0x0000ff00) | ((aColor.GetRed() << 16) & 0x00ff0000); } sal_uInt32 SalPrinterBmp::GetPixelRGB(sal_uInt32 nRow, sal_uInt32 nColumn) const { Scanline pScan = mpScanAccess + nRow * mnScanOffset; BitmapColor aColor = mpFncGetPixel(pScan, nColumn, mpBmpBuffer->maColorMask); if (!!mpBmpBuffer->maPalette) GetPaletteColor(aColor.GetIndex()); return ((aColor.GetBlue()) & 0x000000ff) | ((aColor.GetGreen() << 8) & 0x0000ff00) | ((aColor.GetRed() << 16) & 0x00ff0000); } sal_uInt8 SalPrinterBmp::GetPixelGray(sal_uInt32 nRow, sal_uInt32 nColumn) const { Scanline pScan = mpScanAccess + nRow * mnScanOffset; BitmapColor aColor = mpFncGetPixel(pScan, nColumn, mpBmpBuffer->maColorMask); if (!!mpBmpBuffer->maPalette) aColor = mpBmpBuffer->maPalette[aColor.GetIndex()]; return (aColor.GetBlue() * 28UL + aColor.GetGreen() * 151UL + aColor.GetRed() * 77UL) >> 8; } sal_uInt8 SalPrinterBmp::GetPixelIdx(sal_uInt32 nRow, sal_uInt32 nColumn) const { Scanline pScan = mpScanAccess + nRow * mnScanOffset; BitmapColor aColor = mpFncGetPixel(pScan, nColumn, mpBmpBuffer->maColorMask); if (!!mpBmpBuffer->maPalette) return aColor.GetIndex(); else return 0; } GenPspGfxBackend::GenPspGfxBackend(psp::PrinterGfx* pPrinterGfx) : m_pPrinterGfx(pPrinterGfx) { } GenPspGfxBackend::~GenPspGfxBackend() {} void GenPspGfxBackend::Init() {} void GenPspGfxBackend::freeResources() {} bool GenPspGfxBackend::setClipRegion(vcl::Region const& rRegion) { // TODO: support polygonal clipregions here RectangleVector aRectangles; rRegion.GetRegionRectangles(aRectangles); m_pPrinterGfx->BeginSetClipRegion(); for (auto const& rectangle : aRectangles) { const tools::Long nWidth(rectangle.GetWidth()); const tools::Long nHeight(rectangle.GetHeight()); if (nWidth && nHeight) { m_pPrinterGfx->UnionClipRegion(rectangle.Left(), rectangle.Top(), nWidth, nHeight); } } m_pPrinterGfx->EndSetClipRegion(); return true; } void GenPspGfxBackend::ResetClipRegion() { m_pPrinterGfx->ResetClipRegion(); } sal_uInt16 GenPspGfxBackend::GetBitCount() const { return m_pPrinterGfx->GetBitCount(); } tools::Long GenPspGfxBackend::GetGraphicsWidth() const { return 0; } void GenPspGfxBackend::SetLineColor() { m_pPrinterGfx->SetLineColor(); } void GenPspGfxBackend::SetLineColor(Color nColor) { psp::PrinterColor aColor(nColor.GetRed(), nColor.GetGreen(), nColor.GetBlue()); m_pPrinterGfx->SetLineColor(aColor); } void GenPspGfxBackend::SetFillColor() { m_pPrinterGfx->SetFillColor(); } void GenPspGfxBackend::SetFillColor(Color nColor) { psp::PrinterColor aColor(nColor.GetRed(), nColor.GetGreen(), nColor.GetBlue()); m_pPrinterGfx->SetFillColor(aColor); } void GenPspGfxBackend::SetXORMode(bool bSet, bool /*bInvertOnly*/) { SAL_WARN_IF(bSet, "vcl", "Error: PrinterGfx::SetXORMode() not implemented"); } void GenPspGfxBackend::SetROPLineColor(SalROPColor /*nROPColor*/) { SAL_WARN("vcl", "Error: PrinterGfx::SetROPLineColor() not implemented"); } void GenPspGfxBackend::SetROPFillColor(SalROPColor /*nROPColor*/) { SAL_WARN("vcl", "Error: PrinterGfx::SetROPFillColor() not implemented"); } void GenPspGfxBackend::drawPixel(tools::Long nX, tools::Long nY) { m_pPrinterGfx->DrawPixel(Point(nX, nY)); } void GenPspGfxBackend::drawPixel(tools::Long nX, tools::Long nY, Color nColor) { psp::PrinterColor aColor(nColor.GetRed(), nColor.GetGreen(), nColor.GetBlue()); m_pPrinterGfx->DrawPixel(Point(nX, nY), aColor); } void GenPspGfxBackend::drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2) { m_pPrinterGfx->DrawLine(Point(nX1, nY1), Point(nX2, nY2)); } void GenPspGfxBackend::drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight) { m_pPrinterGfx->DrawRect(tools::Rectangle(Point(nX, nY), Size(nWidth, nHeight))); } void GenPspGfxBackend::drawPolyLine(sal_uInt32 nPoints, const Point* pPointArray) { m_pPrinterGfx->DrawPolyLine(nPoints, pPointArray); } void GenPspGfxBackend::drawPolygon(sal_uInt32 nPoints, const Point* pPointArray) { // Point must be equal to Point! see include/vcl/salgtype.hxx m_pPrinterGfx->DrawPolygon(nPoints, pPointArray); } void GenPspGfxBackend::drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints, const Point** pPointArray) { m_pPrinterGfx->DrawPolyPolygon(nPoly, pPoints, pPointArray); } bool GenPspGfxBackend::drawPolyPolygon(const basegfx::B2DHomMatrix& /*rObjectToDevice*/, const basegfx::B2DPolyPolygon&, double /*fTransparency*/) { // TODO: implement and advertise OutDevSupportType::B2DDraw support return false; } bool GenPspGfxBackend::drawPolyLine(const basegfx::B2DHomMatrix& /*rObjectToDevice*/, const basegfx::B2DPolygon& /*rPolygon*/, double /*fTransparency*/, double /*fLineWidth*/, const std::vector* /*pStroke*/, basegfx::B2DLineJoin, css::drawing::LineCap, double /*fMiterMinimumAngle*/, bool /*bPixelSnapHairline*/) { // TODO: a PS printer can draw B2DPolyLines almost directly return false; } bool GenPspGfxBackend::drawPolyLineBezier(sal_uInt32 nPoints, const Point* pPointArray, const PolyFlags* pFlagArray) { m_pPrinterGfx->DrawPolyLineBezier(nPoints, pPointArray, pFlagArray); return true; } bool GenPspGfxBackend::drawPolygonBezier(sal_uInt32 nPoints, const Point* pPointArray, const PolyFlags* pFlagArray) { m_pPrinterGfx->DrawPolygonBezier(nPoints, pPointArray, pFlagArray); return true; } bool GenPspGfxBackend::drawPolyPolygonBezier(sal_uInt32 nPoly, const sal_uInt32* pPoints, const Point* const* pPointArray, const PolyFlags* const* pFlagArray) { // Point must be equal to Point! see include/vcl/salgtype.hxx m_pPrinterGfx->DrawPolyPolygonBezier(nPoly, pPoints, pPointArray, pFlagArray); return true; } void GenPspGfxBackend::copyArea(tools::Long /*nDestX*/, tools::Long /*nDestY*/, tools::Long /*nSrcX*/, tools::Long /*nSrcY*/, tools::Long /*nSrcWidth*/, tools::Long /*nSrcHeight*/, bool /*bWindowInvalidate*/) { OSL_FAIL("Error: PrinterGfx::CopyArea() not implemented"); } void GenPspGfxBackend::copyBits(const SalTwoRect& /*rPosAry*/, SalGraphics* /*pSrcGraphics*/) { OSL_FAIL("Error: PrinterGfx::CopyBits() not implemented"); } void GenPspGfxBackend::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap) { tools::Rectangle aSrc(Point(rPosAry.mnSrcX, rPosAry.mnSrcY), Size(rPosAry.mnSrcWidth, rPosAry.mnSrcHeight)); tools::Rectangle aDst(Point(rPosAry.mnDestX, rPosAry.mnDestY), Size(rPosAry.mnDestWidth, rPosAry.mnDestHeight)); BitmapBuffer* pBuffer = const_cast(rSalBitmap).AcquireBuffer(BitmapAccessMode::Read); SalPrinterBmp aBmp(pBuffer); m_pPrinterGfx->DrawBitmap(aDst, aSrc, aBmp); const_cast(rSalBitmap).ReleaseBuffer(pBuffer, BitmapAccessMode::Read); } void GenPspGfxBackend::drawBitmap(const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rSalBitmap*/, const SalBitmap& /*rMaskBitmap*/) { OSL_FAIL("Error: no PrinterGfx::DrawBitmap() for transparent bitmap"); } void GenPspGfxBackend::drawMask(const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rSalBitmap*/, Color /*nMaskColor*/) { OSL_FAIL("Error: PrinterGfx::DrawMask() not implemented"); } std::shared_ptr GenPspGfxBackend::getBitmap(tools::Long /*nX*/, tools::Long /*nY*/, tools::Long /*nWidth*/, tools::Long /*nHeight*/) { SAL_INFO("vcl", "Warning: PrinterGfx::GetBitmap() not implemented"); return nullptr; } Color GenPspGfxBackend::getPixel(tools::Long /*nX*/, tools::Long /*nY*/) { OSL_FAIL("Warning: PrinterGfx::GetPixel() not implemented"); return Color(); } void GenPspGfxBackend::invert(tools::Long /*nX*/, tools::Long /*nY*/, tools::Long /*nWidth*/, tools::Long /*nHeight*/, SalInvert /*nFlags*/) { OSL_FAIL("Warning: PrinterGfx::Invert() not implemented"); } void GenPspGfxBackend::invert(sal_uInt32 /*nPoints*/, const Point* /*pPtAry*/, SalInvert /*nFlags*/) { SAL_WARN("vcl", "Error: PrinterGfx::Invert() not implemented"); } bool GenPspGfxBackend::drawEPS(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, void* pPtr, sal_uInt32 nSize) { return m_pPrinterGfx->DrawEPS(tools::Rectangle(Point(nX, nY), Size(nWidth, nHeight)), pPtr, nSize); } bool GenPspGfxBackend::blendBitmap(const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rBitmap*/) { return false; } bool GenPspGfxBackend::blendAlphaBitmap(const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rSrcBitmap*/, const SalBitmap& /*rMaskBitmap*/, const SalBitmap& /*rAlphaBitmap*/) { return false; } bool GenPspGfxBackend::drawAlphaBitmap(const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rSourceBitmap*/, const SalBitmap& /*rAlphaBitmap*/) { return false; } bool GenPspGfxBackend::drawTransformedBitmap(const basegfx::B2DPoint& /*rNull*/, const basegfx::B2DPoint& /*rX*/, const basegfx::B2DPoint& /*rY*/, const SalBitmap& /*rSourceBitmap*/, const SalBitmap* /*pAlphaBitmap*/, double /*fAlpha*/) { return false; } bool GenPspGfxBackend::hasFastDrawTransformedBitmap() const { return false; } bool GenPspGfxBackend::drawAlphaRect(tools::Long /*nX*/, tools::Long /*nY*/, tools::Long /*nWidth*/, tools::Long /*nHeight*/, sal_uInt8 /*nTransparency*/) { return false; } bool GenPspGfxBackend::drawGradient(const tools::PolyPolygon& /*rPolygon*/, const Gradient& /*rGradient*/) { return false; } bool GenPspGfxBackend::implDrawGradient(basegfx::B2DPolyPolygon const& /*rPolyPolygon*/, SalGradient const& /*rGradient*/) { return false; } bool GenPspGfxBackend::supportsOperation(OutDevSupportType /*eType*/) const { return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */