ADTF_DISPLAY_TOOLBOX  3.8.0 (ADTF 3.14.3)
Source Code for Demo 2D GCL Drawer
Location
./src/examples/src/gcldrawer
This example shows:
  • how to create a custom drawer.
  • how to use the cGCLProcessor to interpret GCL Commands.
  • how to use the canvas inside the Draw method.
  • how to send GCL Commands via anADTF Sample.
Header
#pragma once
#include <memory>
class cGCLDrawer : public adtf::ucom::object<adtf::disptb::drawerlib::cDrawer>
{
public:
ADTF_CLASS_ID_NAME(
cGCLDrawer,
"demo_gcl.2d_drawer.disptb.cid",
"Demo 2D GCL Drawer"
);
cGCLDrawer();
~cGCLDrawer() = default;
tResult Init(tInitStage eStage) override;
tResult Shutdown(tInitStage eStage) override;
tResult Draw(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas) override;
tResult ContextCreated(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas) override;
protected:
tInt GetGCLBlockFromSample(const adtf::ucom::iobject_ptr<const adtf::streaming::ISample>& pSample);
private:
tResult CreateFonts(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas);
private:
adtf::filter::cPinReader m_oReader;
adtf_util::cMemoryBlock m_oGCLBlock;
adtf::mediadescription::cSampleCodecFactory m_oCodecFactory;
std::unique_ptr<adtf::disptb::graphicslib::IFont> m_pSmallFont;
std::unique_ptr<adtf::disptb::graphicslib::IFont> m_pNormalFont;
std::unique_ptr<adtf::disptb::graphicslib::IFont> m_pHugeFont;
adtf::base::property_variable<adtf_util::cString> m_strFontName = adtf_util::cString("Arial");
adtf::base::property_variable<tUInt> m_nSmallFontSize = 11;
adtf::base::property_variable<tUInt> m_nMediumFontSize = 16;
adtf::base::property_variable<tUInt> m_nHugeFontSize = 24;
};
Graphics command language processing class.
Definition: gcl.h:64
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
#pragma once
#include <adtffiltersdk/filter.h>
class cObjectGenerator : public adtf::filter::cFilter
{
public:
ADTF_CLASS_ID_NAME(cObjectGenerator,
"create_gcl_object.filter.disptb.cid";,
"Demo GCL Generator Filter");
public:
cObjectGenerator();
virtual ~cObjectGenerator();
tResult Process(adtf::base::tNanoSeconds tmTimeOfTrigger,
adtf::streaming::IRunner* pRunner) override;
private:
tResult CreateObjects(adtf::base::tNanoSeconds tmTimeOfTrigger);
tResult Init();
private:
adtf::streaming::ISampleWriter* m_oPinWriter = nullptr;
};
The IDynamicMemoryBlock interface extends allocated memory dynamically.
Implementation
#include "gcl_drawer.h"
using namespace adtf_util;
using namespace ddl;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
using namespace adtf::disptb::graphicslib;
cGCLDrawer::cGCLDrawer()
{
m_strFontName.SetDescription("Font to use for the overlay.");
RegisterPropertyVariable("font/name", m_strFontName);
m_nSmallFontSize.SetDescription("Size for the small font overlay.");
RegisterPropertyVariable("font/size/small", m_nSmallFontSize);
m_nMediumFontSize.SetDescription("Size for the medium font overlay.");
RegisterPropertyVariable("font/size/medium", m_nMediumFontSize);
m_nHugeFontSize.SetDescription("Size for the huge font overlay.");
RegisterPropertyVariable("font/size/huge", m_nHugeFontSize);
object_ptr<IStreamType> pType = make_object_ptr<cStreamType>(stream_meta_type_gcl());
create_pin(*this, m_oReader, "in1", pType);
SetDescription("in1", "Input pin for GCL commands.");
SetDescription("Use this Drawer to paint a received GCL-Commands onto the canvas.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_2d_gcl_drawer_readme.html");
}
tResult cGCLDrawer::Init(tInitStage eStage)
{
RETURN_IF_FAILED(cDrawer::Init(eStage));
RETURN_NOERROR;
}
tResult cGCLDrawer::Shutdown(tInitStage eStage)
{
RETURN_IF_FAILED(cDrawer::Shutdown(eStage));
RETURN_NOERROR;
}
tResult cGCLDrawer::Draw(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas)
{
adtf::ucom::object_ptr<const adtf::streaming::ISample> pSample;
RETURN_IF_FAILED(m_oReader.GetLastSample(pSample));
if (pSample)
{
// get the memory block from sample and the size of this block
tInt nSize = GetGCLBlockFromSample(pSample);
if (nSize > 0 && m_oGCLBlock.GetPtr() != nullptr)
{
pCanvas->EnableAlpha();
cRect rcArea(0, 0, 0, 0);
pCanvas->PushFlags();
pCanvas->SetFlag(CANVAS_FLAG_TEXT_SCALE_WITH_COORDINATE_SYSTEM, 1);
pCanvas->SetFlag(CANVAS_FLAG_TEXT_ROTATE_WITH_COORDINATE_SYSTEM, 1);
pCanvas->SetFlag(CANVAS_FLAG_TEXT_FLIP_HORIZONTALLY, 0);
pCanvas->SetFlag(CANVAS_FLAG_TEXT_BASELINE_ON_TOP, 1);
m_oGCLProcessor.Process(pCanvas.Get(), m_oGCLBlock.GetPtr(), nSize, 0, 0, rcArea);
pCanvas->PopFlags();
pCanvas->DisableAlpha();
}
}
else
{
m_oGCLBlock.Free();
}
RETURN_NOERROR;
}
tResult cGCLDrawer::ContextCreated(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas)
{
// init the default fonts for out gcl processor
RETURN_IF_FAILED(CreateFonts(pCanvas));
RETURN_NOERROR;
}
tInt cGCLDrawer::GetGCLBlockFromSample(const adtf::ucom::iobject_ptr<const adtf::streaming::ISample>& pSample)
{
tInt nCmdSize = -1;
adtf::ucom::object_ptr_shared_locked<const adtf::streaming::ISampleBuffer> pBuffer;
if (IS_OK(pSample->Lock(pBuffer)))
{
nCmdSize = (tInt) pBuffer->GetSize();
if (nCmdSize > 0)
{
pBuffer->Read(adtf_memory_intf(m_oGCLBlock));
}
else
{
m_oGCLBlock.Free();
}
}
return nCmdSize;
}
tResult cGCLDrawer::CreateFonts(const adtf::ucom::iobject_ptr<adtf::disptb::graphicslib::ICanvas>& pCanvas)
{
cString strFontName = m_strFontName;
strFontName = strFontName.IsNotEmpty() ? strFontName : cString("Arial");
tInt nSmallSize = m_nSmallFontSize;
nSmallSize = nSmallSize > 0 ? nSmallSize : 11;
tInt nMediumSize = m_nSmallFontSize;
nMediumSize = nMediumSize > 0 ? nMediumSize : 16;
tInt nHugeSize = m_nSmallFontSize;
nHugeSize = nHugeSize > 0 ? nHugeSize : 24;
m_pSmallFont.reset(pCanvas->CreateFont(strFontName, nSmallSize, adtf::disptb::graphicslib::IFont::STYLE_Default));
m_pNormalFont.reset(pCanvas->CreateFont(strFontName, nMediumSize, adtf::disptb::graphicslib::IFont::STYLE_Default));
m_pHugeFont.reset(pCanvas->CreateFont(strFontName, nHugeSize, adtf::disptb::graphicslib::IFont::STYLE_Default));
RETURN_IF_FAILED(m_oGCLProcessor.SetFonts(m_pSmallFont.get(), m_pNormalFont.get(), m_pHugeFont.get()));
RETURN_NOERROR;
}
Copyright © Audi Electronics Venture GmbH.
Copyright © Audi Electronics Venture GmbH.
#include "createobject_filter.h"
#include <cmath>
using namespace adtf_util;
using namespace ddl;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
using namespace adtf::disptb::graphicslib;
cObjectGenerator::cObjectGenerator()
{
CreateRunner("object_trigger", cTimerTriggerHint(std::chrono::milliseconds{100}));
SetDescription("object_trigger", "Runner to periodically trigger the function which generates the GCL commands.");
object_ptr<IStreamType> pStreamType = make_object_ptr<cStreamType>(stream_meta_type_gcl());
m_oPinWriter = CreateOutputPin("out_GCLList", pStreamType);
SetDescription("out_GCLList", "Output pin for generated GCL commands.");
SetDescription("Use this Filter to create GCL commands.");
SetHelpLink("$(ADTF_DISPLAY_TOOLBOX_DIR)/doc/displaytoolbox_html/page_2d_gcl_drawer_readme.html");
THROW_IF_FAILED(cGCLWriter::GetDynamicMemoryBlock(m_pCommandBlock));
}
cObjectGenerator::~cObjectGenerator()
{
cGCLWriter::FreeDynamicMemoryBlock(m_pCommandBlock);
}
tResult cObjectGenerator::Process(adtf::base::tNanoSeconds tmTimeOfTrigger,
adtf::streaming::IRunner* /*pRunner*/)
{
RETURN_IF_FAILED(CreateObjects(tmTimeOfTrigger));
RETURN_NOERROR;
}
tResult cObjectGenerator::CreateObjects(adtf::base::tNanoSeconds tmTimeOfTrigger)
{
// start a fresh command buffer
m_pCommandBlock->Reset();
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FGCOL, cColor(0, 255, 0).GetRGBA());
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FILLRECT, 50, 100, 250, 200);
cString strText = "red text in rectangle";
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FGCOL, cColor(255, 0, 0).GetRGBA());
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT_SIZE_SMALL);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT, 55, 120, static_cast<int>(strText.GetLength()));
cGCLWriter::StoreData(m_pCommandBlock, static_cast<int>(strText.GetLength()), strText.GetPtr());
strText = "small blue text";
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FGCOL, cColor(0, 0, 255).GetRGBA());
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT, 10, 20, static_cast<int>(strText.GetLength()));
cGCLWriter::StoreData(m_pCommandBlock, static_cast<int>(strText.GetLength()), strText.GetPtr());
strText = "medium red text";
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FGCOL, cColor(255, 0, 0).GetRGBA());
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT_SIZE_NORMAL);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT, 15, 40, static_cast<int>(strText.GetLength()));
cGCLWriter::StoreData(m_pCommandBlock, static_cast<int>(strText.GetLength()), strText.GetPtr());
strText = "huge black text";
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_FGCOL, cColor(0, 0, 0).GetRGBA());
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT_SIZE_HUGE);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_TEXT, 20, 70, static_cast<int>(strText.GetLength()));
cGCLWriter::StoreData(m_pCommandBlock, static_cast<int>(strText.GetLength()), strText.GetPtr());
{
constexpr tInt nX = -50;
constexpr tInt nY = 50;
constexpr tInt nRadius = 30;
constexpr tUInt64 nTicksPerSecond = 1000000000;
constexpr tUInt64 nTicksPerMinute = 60000000000;
constexpr tFloat64 fTwoPi = 2 * 3.14159265358979311600;
// circle
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_DRAWCIRCLE, nX, nY, nRadius * 2);
// animation, absolute lines
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_DRAWLINE,
nX, nY,
nX + static_cast<tInt>(std::sin((tmTimeOfTrigger.nCount % nTicksPerSecond) * fTwoPi / nTicksPerSecond) * nRadius),
nY + static_cast<tInt>(std::cos((tmTimeOfTrigger.nCount % nTicksPerSecond) * fTwoPi / nTicksPerSecond) * nRadius)
);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINEWIDTH, 3);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_DRAWLINE,
nX, nY,
nX + static_cast<tInt>(std::sin((tmTimeOfTrigger.nCount % nTicksPerMinute) * fTwoPi / nTicksPerMinute) * nRadius),
nY + static_cast<tInt>(std::cos((tmTimeOfTrigger.nCount % nTicksPerMinute) * fTwoPi / nTicksPerMinute) * nRadius)
);
// animation, point-wise drawing
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINEWIDTH, 1);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_MOVETO, nX, nY + nRadius);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINETO, nX + nRadius, nY);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINETO, nX, nY - nRadius);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINETO, nX - nRadius, nY);
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_LINETO, nX, nY + nRadius);
}
// mandatory end-of-commands marker, nothing beyond this point would be visible
cGCLWriter::StoreCommand(m_pCommandBlock, GCL_CMD_END);
object_ptr<ISample> pSample;
// data generating filter should use tmTimeOfTrigger as sample time
RETURN_IF_FAILED(alloc_sample(pSample, tmTimeOfTrigger));
{
// scoped buffer lock
object_ptr_locked<ISampleBuffer> pBuffer;
RETURN_IF_FAILED(pSample->WriteLock(pBuffer, m_pCommandBlock->GetSize()));
pBuffer->Write(adtf_memory_buffer<tVoid>(m_pCommandBlock->GetPtr(), m_pCommandBlock->GetSize()));
}
m_oPinWriter->Write(pSample);
RETURN_NOERROR;
}
Copyright © Audi Electronics Venture GmbH.