From fe6590366df9eba3e530a15f2fd098ee50acbfaf Mon Sep 17 00:00:00 2001 From: Kirill Polyakov Date: Thu, 23 Nov 2023 16:32:27 +0300 Subject: [PATCH] Added implementation of graphic layers --- DesktopEditor/graphics/Graphics.cpp | 114 +++++++++++++++++++- DesktopEditor/graphics/Graphics.h | 13 +++ DesktopEditor/graphics/GraphicsLayer.cpp | 50 +++++++++ DesktopEditor/graphics/GraphicsLayer.h | 80 ++++++++++++++ DesktopEditor/graphics/GraphicsRenderer.cpp | 15 +++ DesktopEditor/graphics/GraphicsRenderer.h | 3 + DesktopEditor/graphics/IRenderer.h | 2 + DesktopEditor/graphics/pro/Graphics.h | 3 + DesktopEditor/graphics/pro/graphics.pro | 7 ++ 9 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 DesktopEditor/graphics/GraphicsLayer.cpp create mode 100644 DesktopEditor/graphics/GraphicsLayer.h diff --git a/DesktopEditor/graphics/Graphics.cpp b/DesktopEditor/graphics/Graphics.cpp index 769310a6d6..48c685f300 100644 --- a/DesktopEditor/graphics/Graphics.cpp +++ b/DesktopEditor/graphics/Graphics.cpp @@ -105,7 +105,9 @@ namespace Aggplus #endif m_dDpiTile = -1; - + + m_pAlphaMask = NULL; + m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -146,7 +148,9 @@ namespace Aggplus #endif m_dDpiTile = -1; - + + m_pAlphaMask = NULL; + m_nTextRenderMode = FT_RENDER_MODE_NORMAL; m_nBlendMode = agg::comp_op_src_over; @@ -161,6 +165,12 @@ namespace Aggplus #endif RELEASEINTERFACE(m_pAlphaMask); + + while (!m_arLayers.empty()) + { + RELEASEINTERFACE(m_arLayers.top()); + m_arLayers.pop(); + } } INT CGraphics::IsDib() @@ -1242,6 +1252,106 @@ namespace Aggplus m_pAlphaMask->m_internal->StartApplying(); return Ok; } + + Status CGraphics::AddLayer(CGraphicsLayer *pGraphicsLayer) + { + if (NULL == pGraphicsLayer || pGraphicsLayer->Empty()) + return InvalidParameter; + + m_arLayers.push(pGraphicsLayer); + pGraphicsLayer->AddRef(); + + int nStride = m_frame_buffer.ren_buf().stride(); + const unsigned int unWidth = m_frame_buffer.ren_buf().width(); + const unsigned int unHeight = m_frame_buffer.ren_buf().height(); + + m_frame_buffer.create(unWidth, unHeight, false, nStride, pGraphicsLayer->GetBuffer()); + + return Ok; + } + + Status CGraphics::CreateLayer() + { + int nStride = m_frame_buffer.ren_buf().stride(); + const unsigned int unWidth = m_frame_buffer.ren_buf().width(); + const unsigned int unHeight = m_frame_buffer.ren_buf().height(); + + BYTE *pBuffer = new BYTE[unWidth * unHeight * m_frame_buffer.pix_size]; + + for (unsigned long unIndex = 0; unIndex < unWidth * unHeight * m_frame_buffer.pix_size; unIndex += 4) + ((BYTE*)pBuffer)[unIndex + pixfmt_type::order_type::A] = 0x00; + + m_frame_buffer.create(unWidth, unHeight, false, nStride, pBuffer); + + m_arLayers.push(new CGraphicsLayer(pBuffer, false)); + return Ok; + } + + Status CGraphics::BlendLayer() + { + if (m_arLayers.empty()) + return WrongState; + + CGraphicsLayer *pCurrentGraphicsLayer = m_arLayers.top(); + m_arLayers.pop(); + + BYTE* pBuffer = NULL; + + if (!m_arLayers.empty()) + pBuffer = m_arLayers.top()->GetBuffer(); + else + pBuffer = m_pPixels; + + if (NULL == pBuffer) + { + RELEASEINTERFACE(pCurrentGraphicsLayer); + return WrongState; + } + + agg::rendering_buffer *pRenBuffer = &GetRenderingBuffer(); + + pRenBuffer->attach(pBuffer, m_frame_buffer.ren_buf().width(), m_frame_buffer.ren_buf().height(), pRenBuffer->stride()); + + pCurrentGraphicsLayer->BlendTo(m_frame_buffer.pixfmt()); + + RELEASEINTERFACE(pCurrentGraphicsLayer); + return Ok; + } + + Status CGraphics::RemoveLayer() + { + if (m_arLayers.empty()) + return WrongState; + + CGraphicsLayer *pCurrentGraphicsLayer = m_arLayers.top(); + m_arLayers.pop(); + + RELEASEINTERFACE(pCurrentGraphicsLayer); + return Ok; + } + + Status CGraphics::SetLayerSettings(const TGraphicsLayerSettings &oSettings) + { + if (m_arLayers.empty()) + return WrongState; + + m_arLayers.top()->SetSettings(oSettings); + + return Ok; + } + + Status CGraphics::SetLayerOpacity(double dOpacity) + { + if (dOpacity < 0. || dOpacity > 1.) + return InvalidParameter; + + if (m_arLayers.empty()) + return WrongState; + + m_arLayers.top()->SetOpacity(dOpacity); + + return Ok; + } void CGraphics::CalculateFullTransform() { diff --git a/DesktopEditor/graphics/Graphics.h b/DesktopEditor/graphics/Graphics.h index 8895dbfa2a..87f0969477 100644 --- a/DesktopEditor/graphics/Graphics.h +++ b/DesktopEditor/graphics/Graphics.h @@ -64,6 +64,7 @@ #include "Color.h" #include "Matrix.h" +#include "GraphicsLayer.h" #include "GraphicsPath.h" #include "AlphaMask.h" #include "Clip.h" @@ -71,6 +72,7 @@ #include "Image.h" #include "../fontengine/FontManager.h" +#include #include #if defined(_WIN32) || defined (_WIN64) @@ -281,6 +283,8 @@ protected: CAlphaMask* m_pAlphaMask; + std::stack m_arLayers; + agg::svg::frame_buffer_rgba m_frame_buffer; agg::svg::rasterizer m_rasterizer; @@ -402,6 +406,15 @@ public: Status ResetAlphaMask(); Status StartApplyingAlphaMask(); + //Работа со слоями + Status AddLayer(CGraphicsLayer* pGraphicsLayer); + Status CreateLayer(); + Status BlendLayer(); + Status RemoveLayer(); + + Status SetLayerSettings(const TGraphicsLayerSettings& oSettings); + Status SetLayerOpacity(double dOpacity); + void CalculateFullTransform(); bool IsClip(); diff --git a/DesktopEditor/graphics/GraphicsLayer.cpp b/DesktopEditor/graphics/GraphicsLayer.cpp new file mode 100644 index 0000000000..5c223f41e4 --- /dev/null +++ b/DesktopEditor/graphics/GraphicsLayer.cpp @@ -0,0 +1,50 @@ +#include "GraphicsLayer.h" + +namespace Aggplus +{ + CGraphicsLayer::CGraphicsLayer(BYTE *pBuffer, bool bExternalBuffer) + : m_pBuffer(pBuffer), m_bExternalBuffer(NULL != pBuffer && bExternalBuffer) + { + SetDefaultSettings(); + } + + CGraphicsLayer::~CGraphicsLayer() + { + if (!m_bExternalBuffer) + RELEASEARRAYOBJECTS(m_pBuffer); + } + + bool CGraphicsLayer::Empty() const + { + return NULL == m_pBuffer; + } + + BYTE *CGraphicsLayer::GetBuffer() + { + return m_pBuffer; + } + + void CGraphicsLayer::SetDefaultSettings() + { + m_oSettings.m_dOpacity = 1.; + } + + void CGraphicsLayer::SetSettings(const TGraphicsLayerSettings &oSettings) + { + m_oSettings = oSettings; + } + + const TGraphicsLayerSettings &CGraphicsLayer::GetSettings() const + { + return m_oSettings; + } + + void CGraphicsLayer::SetOpacity(double dOpacity) + { + if (dOpacity > 1. || dOpacity < 0.) + m_oSettings.m_dOpacity = 1.; + else + m_oSettings.m_dOpacity = dOpacity; + } +} + diff --git a/DesktopEditor/graphics/GraphicsLayer.h b/DesktopEditor/graphics/GraphicsLayer.h new file mode 100644 index 0000000000..c6dd6cad45 --- /dev/null +++ b/DesktopEditor/graphics/GraphicsLayer.h @@ -0,0 +1,80 @@ +#ifndef CGRAPHICSLAYER_H +#define CGRAPHICSLAYER_H + +#include "Defines.h" +#include "./config.h" +#include "../common/IGrObject.h" + +namespace Aggplus +{ + struct TGraphicsLayerSettings + { + double m_dOpacity; + }; + + class GRAPHICS_DECL CGraphicsLayer : public IGrObject + { + public: + CGraphicsLayer(BYTE* pBuffer, bool bExternalBuffer = true); + ~CGraphicsLayer(); + + bool Empty() const; + BYTE* GetBuffer(); + + void SetDefaultSettings(); + + void SetSettings(const TGraphicsLayerSettings& oSettings); + const TGraphicsLayerSettings& GetSettings() const; + + void SetOpacity(double dOpacity); + + template + void BlendTo(SrcPixelFormatRenderer& oSrc) + { + if (NULL == m_pBuffer) + return; + + typedef typename SrcPixelFormatRenderer::order_type order_type; + typedef typename SrcPixelFormatRenderer::value_type value_type; + + int nStep = 4; + BYTE* pSrcBuffer = m_pBuffer; + value_type* pDstBuffer = NULL; + BYTE uchAlpha; + + for (unsigned int unY = 0; unY < oSrc.height(); ++unY) + { + pDstBuffer = oSrc.row_ptr(unY); + for (unsigned int unX = 0; unX < oSrc.width(); ++unX) + { + uchAlpha = (pSrcBuffer[order_type::A] * ((value_type)(m_oSettings.m_dOpacity * 255.)) + 1) >> 8; + if(uchAlpha) + { + if(uchAlpha == SrcPixelFormatRenderer::base_mask) + { + pDstBuffer[order_type::R] = pSrcBuffer[order_type::R]; + pDstBuffer[order_type::G] = pSrcBuffer[order_type::G]; + pDstBuffer[order_type::B] = pSrcBuffer[order_type::B]; + pDstBuffer[order_type::A] = SrcPixelFormatRenderer::base_mask; + } + else + { + SrcPixelFormatRenderer::blender_type::blend_pix(pDstBuffer, pSrcBuffer[order_type::R], pSrcBuffer[order_type::G], pSrcBuffer[order_type::B], uchAlpha); + } + } + + pSrcBuffer += nStep; + pDstBuffer += nStep; + } + } + } + private: + BYTE* m_pBuffer; + bool m_bExternalBuffer; + + TGraphicsLayerSettings m_oSettings; + }; + +} + +#endif // CGRAPHICSLAYER_H diff --git a/DesktopEditor/graphics/GraphicsRenderer.cpp b/DesktopEditor/graphics/GraphicsRenderer.cpp index 7304897791..7402a1ecf5 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.cpp +++ b/DesktopEditor/graphics/GraphicsRenderer.cpp @@ -799,6 +799,11 @@ HRESULT CGraphicsRenderer::BeginCommand(const DWORD& lType) m_pRenderer->CreateAlphaMask(); break; } + case c_nLayerType: + { + m_pRenderer->CreateLayer(); + break; + } default: break; }; @@ -838,6 +843,11 @@ HRESULT CGraphicsRenderer::EndCommand(const DWORD& lType) m_pRenderer->ResetAlphaMask(); break; } + case c_nLayerType: + { + m_pRenderer->BlendLayer(); + break; + } default: break; }; @@ -1406,6 +1416,11 @@ void CGraphicsRenderer::SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask) m_pRenderer->SetAlphaMask(pAlphaMask); } +void CGraphicsRenderer::SetLayerOpacity(double dOpacity) +{ + m_pRenderer->SetLayerOpacity(dOpacity); +} + void CGraphicsRenderer::put_GlobalAlphaEnabled(const bool& bEnabled, const double& dVal) { m_bGlobalAlphaEnabled = bEnabled; diff --git a/DesktopEditor/graphics/GraphicsRenderer.h b/DesktopEditor/graphics/GraphicsRenderer.h index e0d67d8628..ef2f314208 100644 --- a/DesktopEditor/graphics/GraphicsRenderer.h +++ b/DesktopEditor/graphics/GraphicsRenderer.h @@ -351,6 +351,9 @@ public: // alpha mask methods void SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask); + + // layer methods + void SetLayerOpacity(double dOpacity); // smart methods void drawHorLine(BYTE align, double y, double x, double r, double penW) diff --git a/DesktopEditor/graphics/IRenderer.h b/DesktopEditor/graphics/IRenderer.h index 849f6e6d56..0fd87bbd3a 100644 --- a/DesktopEditor/graphics/IRenderer.h +++ b/DesktopEditor/graphics/IRenderer.h @@ -67,6 +67,8 @@ const long c_nTableCell = 0x2000; const long c_nMaskType = 0x3000; const long c_nResetMaskType = 0x4000; +const long c_nLayerType = 0x5000; + const long c_nPDFTilingFill = 0x2001; const long c_nPDFTilingFillIteration = 0x2002; diff --git a/DesktopEditor/graphics/pro/Graphics.h b/DesktopEditor/graphics/pro/Graphics.h index 508b1dca98..e98d28a9ab 100644 --- a/DesktopEditor/graphics/pro/Graphics.h +++ b/DesktopEditor/graphics/pro/Graphics.h @@ -121,6 +121,9 @@ namespace NSGraphics //alpha mask methods virtual void SetAlphaMask(Aggplus::CAlphaMask* pAlphaMask) = 0; + //layer methods + virtual void SetLayerOpacity(double dOpacity) = 0; + // smart methods virtual void drawHorLine(BYTE align, double y, double x, double r, double penW) = 0; virtual void drawHorLine2(BYTE align, double y, double x, double r, double penW) = 0; diff --git a/DesktopEditor/graphics/pro/graphics.pro b/DesktopEditor/graphics/pro/graphics.pro index ce20b972e5..04483815a7 100644 --- a/DesktopEditor/graphics/pro/graphics.pro +++ b/DesktopEditor/graphics/pro/graphics.pro @@ -63,6 +63,13 @@ SOURCES += \ ./../AlphaMask_private.cpp \ ./../AlphaMask.cpp +# grapgics layer +HEADERS += \ + ./../GraphicsLayer.h + +SOURCES += \ + ./../GraphicsLayer.cpp + SOURCES += \ $$GRAPHICS_AGG_PATH/src/agg_arc.cpp \ $$GRAPHICS_AGG_PATH/src/agg_bezier_arc.cpp \