# HG changeset patch # User Sebastien Jodogne # Date 1556292498 -7200 # Node ID 9e51fb773bbd6394c6f3affcfb8802ab5917f550 # Parent b716763571ad009944fc2fd01d0bfe537bf2945e CairoCompositor diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/CairoCompositor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/CairoCompositor.cpp Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,177 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CairoCompositor.h" + +#include "Internals/CairoColorTextureRenderer.h" +#include "Internals/CairoFloatTextureRenderer.h" +#include "Internals/CairoInfoPanelRenderer.h" +#include "Internals/CairoPolylineRenderer.h" +#include "Internals/CairoTextRenderer.h" + +#include + +namespace OrthancStone +{ + cairo_t* CairoCompositor::GetCairoContext() + { + if (context_.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + else + { + return context_->GetObject(); + } + } + + + Internals::CompositorHelper::ILayerRenderer* CairoCompositor::Create(const ISceneLayer& layer) + { + switch (layer.GetType()) + { + case ISceneLayer::Type_Polyline: + return new Internals::CairoPolylineRenderer(*this, layer); + + case ISceneLayer::Type_InfoPanel: + return new Internals::CairoInfoPanelRenderer(*this, layer); + + case ISceneLayer::Type_ColorTexture: + return new Internals::CairoColorTextureRenderer(*this, layer); + + case ISceneLayer::Type_FloatTexture: + return new Internals::CairoFloatTextureRenderer(*this, layer); + + case ISceneLayer::Type_Text: + { + const TextSceneLayer& l = dynamic_cast(layer); + + Fonts::const_iterator found = fonts_.find(l.GetFontIndex()); + if (found == fonts_.end()) + { + return NULL; + } + else + { + assert(found->second != NULL); + return new Internals::CairoTextRenderer(*this, *found->second, l); + } + } + + default: + return NULL; + } + } + + + CairoCompositor::CairoCompositor(Scene2D& scene, + unsigned int canvasWidth, + unsigned int canvasHeight) : + helper_(scene, *this) + { + canvas_.SetSize(canvasWidth, canvasHeight, false); + } + + + CairoCompositor::~CairoCompositor() + { + for (Fonts::iterator it = fonts_.begin(); it != fonts_.end(); ++it) + { + assert(it->second != NULL); + delete it->second; + } + } + + + void CairoCompositor::SetFont(size_t index, + GlyphBitmapAlphabet* dict) // Takes ownership + { + if (dict == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + } + else + { + std::auto_ptr protection(dict); + + Fonts::iterator found = fonts_.find(index); + + if (found == fonts_.end()) + { + fonts_[index] = protection.release(); + } + else + { + assert(found->second != NULL); + delete found->second; + + found->second = protection.release(); + } + } + } + + +#if ORTHANC_ENABLE_LOCALE == 1 + void CairoCompositor::SetFont(size_t index, + Orthanc::EmbeddedResources::FileResourceId resource, + unsigned int fontSize, + Orthanc::Encoding codepage) + { + FontRenderer renderer; + renderer.LoadFont(font, fontSize); + + std::auto_ptr alphabet(new GlyphBitmapAlphabet); + alphabet->LoadCodepage(renderer, codepage); + + SetFont(index, alphabet.release()); + } +#endif + + + void CairoCompositor::Refresh() + { + context_.reset(new CairoContext(canvas_)); + + // https://www.cairographics.org/FAQ/#clear_a_surface + cairo_set_source_rgba(context_->GetObject(), 0, 0, 0, 255); + cairo_paint(context_->GetObject()); + + helper_.Refresh(canvas_.GetWidth(), canvas_.GetHeight()); + context_.reset(); + } + + + Orthanc::ImageAccessor* CairoCompositor::RenderText(size_t fontIndex, + const std::string& utf8) const + { + Fonts::const_iterator found = fonts_.find(fontIndex); + + if (found == fonts_.end()) + { + return NULL; + } + else + { + assert(found->second != NULL); + return found->second->RenderText(utf8); + } + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/CairoCompositor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/CairoCompositor.h Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,86 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Fonts/GlyphBitmapAlphabet.h" +#include "../Viewport/CairoContext.h" +#include "Internals/CompositorHelper.h" +#include "Internals/ICairoContextProvider.h" + +namespace OrthancStone +{ + class CairoCompositor : + private Internals::CompositorHelper::IRendererFactory, + private Internals::ICairoContextProvider + { + private: + typedef std::map Fonts; + + Internals::CompositorHelper helper_; + CairoSurface canvas_; + Fonts fonts_; + + // Only valid during a call to "Refresh()" + std::auto_ptr context_; + + virtual cairo_t* GetCairoContext(); + + virtual unsigned int GetCairoWidth() + { + return canvas_.GetWidth(); + } + + virtual unsigned int GetCairoHeight() + { + return canvas_.GetHeight(); + } + + virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer); + + public: + CairoCompositor(Scene2D& scene, + unsigned int canvasWidth, + unsigned int canvasHeight); + + ~CairoCompositor(); + + const CairoSurface& GetCanvas() const + { + return canvas_; + } + + void SetFont(size_t index, + GlyphBitmapAlphabet* dict); // Takes ownership + +#if ORTHANC_ENABLE_LOCALE == 1 + void SetFont(size_t index, + Orthanc::EmbeddedResources::FileResourceId resource, + unsigned int fontSize, + Orthanc::Encoding codepage); +#endif + + void Refresh(); + + Orthanc::ImageAccessor* RenderText(size_t fontIndex, + const std::string& utf8) const; + }; +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,79 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CairoColorTextureRenderer.h" + +#include "../ColorTextureSceneLayer.h" + +namespace OrthancStone +{ + namespace Internals + { + CairoColorTextureRenderer::CairoColorTextureRenderer(ICairoContextProvider& target, + const ISceneLayer& layer) : + target_(target) + { + Update(layer); + } + + + void CairoColorTextureRenderer::Update(const ISceneLayer& layer) + { + const ColorTextureSceneLayer& l = dynamic_cast(layer); + + texture_.Copy(l.GetTexture(), true); + textureTransform_ = l.GetTransform(); + isLinearInterpolation_ = l.IsLinearInterpolation(); + } + + + void CairoColorTextureRenderer::Render(const AffineTransform2D& transform) + { + cairo_t* cr = target_.GetCairoContext(); + + AffineTransform2D t = + AffineTransform2D::Combine(transform, textureTransform_); + Matrix h = t.GetHomogeneousMatrix(); + + cairo_save(cr); + + cairo_matrix_t m; + cairo_matrix_init(&m, h(0, 0), h(1, 0), h(0, 1), h(1, 1), h(0, 2), h(1, 2)); + cairo_transform(cr, &m); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(cr, texture_.GetObject(), 0, 0); + + if (isLinearInterpolation_) + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); + } + else + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); + } + + cairo_paint(cr); + + cairo_restore(cr); + } + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoColorTextureRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoColorTextureRenderer.h Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,49 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../../Viewport/CairoSurface.h" +#include "CompositorHelper.h" +#include "ICairoContextProvider.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoColorTextureRenderer : public CompositorHelper::ILayerRenderer + { + private: + ICairoContextProvider& target_; + CairoSurface texture_; + AffineTransform2D textureTransform_; + bool isLinearInterpolation_; + + public: + CairoColorTextureRenderer(ICairoContextProvider& target, + const ISceneLayer& layer); + + virtual void Update(const ISceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform); + }; + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,116 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CairoFloatTextureRenderer.h" + +#include "../FloatTextureSceneLayer.h" + +namespace OrthancStone +{ + namespace Internals + { + void CairoFloatTextureRenderer::Update(const ISceneLayer& layer) + { + const FloatTextureSceneLayer& l = dynamic_cast(layer); + + textureTransform_ = l.GetTransform(); + isLinearInterpolation_ = l.IsLinearInterpolation(); + + float windowCenter, windowWidth; + l.GetWindowing(windowCenter, windowWidth); + + const float a = windowCenter - windowWidth; + const float slope = 256.0f / (2.0f * windowWidth); + + const Orthanc::ImageAccessor& source = l.GetTexture(); + const unsigned int width = source.GetWidth(); + const unsigned int height = source.GetHeight(); + texture_.SetSize(width, height, false); + + Orthanc::ImageAccessor target; + texture_.GetWriteableAccessor(target); + + assert(source.GetFormat() == Orthanc::PixelFormat_Float32 && + target.GetFormat() == Orthanc::PixelFormat_BGRA32 && + sizeof(float) == 4); + + for (unsigned int y = 0; y < height; y++) + { + const float* p = reinterpret_cast(source.GetConstRow(y)); + uint8_t* q = reinterpret_cast(target.GetRow(y)); + + for (unsigned int x = 0; x < width; x++) + { + float v = (*p - a) * slope; + if (v <= 0) + { + v = 0; + } + else if (v >= 255) + { + v = 255; + } + + uint8_t vv = static_cast(v); + + q[0] = vv; + q[1] = vv; + q[2] = vv; + + p++; + q += 4; + } + } + } + + + void CairoFloatTextureRenderer::Render(const AffineTransform2D& transform) + { + cairo_t* cr = target_.GetCairoContext(); + + AffineTransform2D t = + AffineTransform2D::Combine(transform, textureTransform_); + Matrix h = t.GetHomogeneousMatrix(); + + cairo_save(cr); + + cairo_matrix_t m; + cairo_matrix_init(&m, h(0, 0), h(1, 0), h(0, 1), h(1, 1), h(0, 2), h(1, 2)); + cairo_transform(cr, &m); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(cr, texture_.GetObject(), 0, 0); + + if (isLinearInterpolation_) + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); + } + else + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); + } + + cairo_paint(cr); + + cairo_restore(cr); + } + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoFloatTextureRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoFloatTextureRenderer.h Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,53 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../../Viewport/CairoSurface.h" +#include "CompositorHelper.h" +#include "ICairoContextProvider.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoFloatTextureRenderer : public CompositorHelper::ILayerRenderer + { + private: + ICairoContextProvider& target_; + CairoSurface texture_; + AffineTransform2D textureTransform_; + bool isLinearInterpolation_; + + public: + CairoFloatTextureRenderer(ICairoContextProvider& target, + const ISceneLayer& layer) : + target_(target) + { + Update(layer); + } + + virtual void Update(const ISceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform); + }; + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoInfoPanelRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoInfoPanelRenderer.cpp Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,73 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CairoInfoPanelRenderer.h" + +#include "../InfoPanelSceneLayer.h" + +namespace OrthancStone +{ + namespace Internals + { + void CairoInfoPanelRenderer::Update(const ISceneLayer& layer) + { + const InfoPanelSceneLayer& l = dynamic_cast(layer); + + texture_.Copy(l.GetTexture(), true); + anchor_ = l.GetAnchor(); + isLinearInterpolation_ = l.IsLinearInterpolation(); + } + + + void CairoInfoPanelRenderer::Render(const AffineTransform2D& transform) + { + int dx, dy; + InfoPanelSceneLayer::ComputeAnchorLocation( + dx, dy, anchor_, texture_.GetWidth(), texture_.GetHeight(), + target_.GetCairoWidth(), target_.GetCairoHeight()); + + cairo_t* cr = target_.GetCairoContext(); + + cairo_save(cr); + + cairo_matrix_t t; + cairo_matrix_init_identity(&t); + cairo_matrix_translate(&t, dx, dy); + cairo_transform(cr, &t); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(cr, texture_.GetObject(), 0, 0); + + if (isLinearInterpolation_) + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); + } + else + { + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); + } + + cairo_paint(cr); + + cairo_restore(cr); + } + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoInfoPanelRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoInfoPanelRenderer.h Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,53 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../../Viewport/CairoSurface.h" +#include "CompositorHelper.h" +#include "ICairoContextProvider.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoInfoPanelRenderer : public CompositorHelper::ILayerRenderer + { + private: + ICairoContextProvider& target_; + CairoSurface texture_; + BitmapAnchor anchor_; + bool isLinearInterpolation_; + + public: + CairoInfoPanelRenderer(ICairoContextProvider& target, + const ISceneLayer& layer) : + target_(target) + { + Update(layer); + } + + virtual void Update(const ISceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform); + }; + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoTextRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoTextRenderer.cpp Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,114 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "CairoTextRenderer.h" + +#include + +namespace OrthancStone +{ + namespace Internals + { + CairoTextRenderer::CairoTextRenderer(ICairoContextProvider& target, + const GlyphBitmapAlphabet& alphabet, + const TextSceneLayer& layer) : + CairoBaseRenderer(target, layer) + { + std::auto_ptr source(alphabet.RenderText(layer.GetText())); + + if (source.get() != NULL) + { + text_.SetSize(source->GetWidth(), source->GetHeight(), true); + + Orthanc::ImageAccessor target; + text_.GetWriteableAccessor(target); + + if (source->GetFormat() != Orthanc::PixelFormat_Grayscale8 || + target.GetFormat() != Orthanc::PixelFormat_BGRA32) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + const unsigned int width = source->GetWidth(); + const unsigned int red = layer.GetRed(); + const unsigned int green = layer.GetGreen(); + const unsigned int blue = layer.GetBlue(); + + for (unsigned int y = 0; y < source->GetHeight(); y++) + { + const uint8_t* p = reinterpret_cast(source->GetConstRow(y)); + uint8_t* q = reinterpret_cast(target.GetRow(y)); + + for (unsigned int x = 0; x < width; x++) + { + unsigned int alpha = *p; + + // Premultiplied alpha + q[0] = static_cast((blue * alpha) / 255); + q[1] = static_cast((green * alpha) / 255); + q[2] = static_cast((red * alpha) / 255); + q[3] = *p; + + p++; + q += 4; + } + } + + cairo_surface_mark_dirty(text_.GetObject()); + } + } + + + void CairoTextRenderer::Render(const AffineTransform2D& transform) + { + if (text_.GetWidth() != 0 && + text_.GetHeight() != 0) + { + const TextSceneLayer& layer = GetLayer(); + + cairo_t* cr = GetCairoContext(); + cairo_set_source_rgb(cr, layer.GetRedAsFloat(), layer.GetGreenAsFloat(), layer.GetBlueAsFloat()); + + double dx, dy; // In pixels + ComputeAnchorTranslation(dx, dy, layer.GetAnchor(), text_.GetWidth(), + text_.GetHeight(), layer.GetBorder()); + + double x = layer.GetX(); + double y = layer.GetY(); + transform.Apply(x, y); + + cairo_save(cr); + + cairo_matrix_t t; + cairo_matrix_init_identity(&t); + cairo_matrix_translate(&t, x + dx, y + dy); + cairo_transform(cr, &t); + + cairo_set_operator(cr, CAIRO_OPERATOR_OVER); + cairo_set_source_surface(cr, text_.GetObject(), 0, 0); + cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_BILINEAR); + cairo_paint(cr); + + cairo_restore(cr); + } + } + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/Internals/CairoTextRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2D/Internals/CairoTextRenderer.h Fri Apr 26 17:28:18 2019 +0200 @@ -0,0 +1,46 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../../Fonts/GlyphBitmapAlphabet.h" +#include "../../Viewport/CairoSurface.h" +#include "../TextSceneLayer.h" +#include "CairoBaseRenderer.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoTextRenderer : public CairoBaseRenderer + { + private: + CairoSurface text_; + + public: + CairoTextRenderer(ICairoContextProvider& target, + const GlyphBitmapAlphabet& alphabet, + const TextSceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform); + }; + } +} diff -r b716763571ad -r 9e51fb773bbd Framework/Scene2D/OpenGLCompositor.h --- a/Framework/Scene2D/OpenGLCompositor.h Fri Apr 26 17:05:14 2019 +0200 +++ b/Framework/Scene2D/OpenGLCompositor.h Fri Apr 26 17:28:18 2019 +0200 @@ -29,7 +29,7 @@ namespace OrthancStone { - class OpenGLCompositor : protected Internals::CompositorHelper::IRendererFactory + class OpenGLCompositor : private Internals::CompositorHelper::IRendererFactory { private: class Font; @@ -48,7 +48,6 @@ const Font* GetFont(size_t fontIndex) const; - protected: virtual Internals::CompositorHelper::ILayerRenderer* Create(const ISceneLayer& layer); public: diff -r b716763571ad -r 9e51fb773bbd Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri Apr 26 17:05:14 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Fri Apr 26 17:28:18 2019 +0200 @@ -257,10 +257,15 @@ #${ORTHANC_STONE_ROOT}/Framework/Layers/SeriesFrameRendererFactory.cpp #${ORTHANC_STONE_ROOT}/Framework/Layers/SingleFrameRendererFactory.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/CairoCompositor.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ColorTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/FloatTextureSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/InfoPanelSceneLayer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoColorTextureRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoFloatTextureRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoInfoPanelRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoPolylineRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CairoTextRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/CompositorHelper.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/Internals/FixedPointAligner.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/PanSceneTracker.cpp