comparison Framework/Wrappers/CairoContext.cpp @ 860:238693c3bc51 am-dev

merge default -> am-dev
author Alain Mazy <alain@mazy.be>
date Mon, 24 Jun 2019 14:35:00 +0200
parents c237e0625065
children 2d8ab34c8c91
comparison
equal deleted inserted replaced
856:a6e17a5a39e7 860:238693c3bc51
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2019 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "CairoContext.h"
23
24 #include <Core/Logging.h>
25 #include <Core/OrthancException.h>
26
27
28 namespace OrthancStone
29 {
30 CairoContext::CairoContext(CairoSurface& surface) :
31 width_(surface.GetWidth()),
32 height_(surface.GetHeight())
33 {
34 context_ = cairo_create(surface.GetObject());
35 if (!context_)
36 {
37 LOG(ERROR) << "Cannot create Cairo drawing context";
38 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
39 }
40 }
41
42
43 CairoContext::~CairoContext()
44 {
45 if (context_ != NULL)
46 {
47 cairo_destroy(context_);
48 context_ = NULL;
49 }
50 }
51
52
53 void CairoContext::SetSourceColor(uint8_t red,
54 uint8_t green,
55 uint8_t blue)
56 {
57 cairo_set_source_rgb(context_,
58 static_cast<float>(red) / 255.0f,
59 static_cast<float>(green) / 255.0f,
60 static_cast<float>(blue) / 255.0f);
61 }
62
63
64 class CairoContext::AlphaSurface : public boost::noncopyable
65 {
66 private:
67 cairo_surface_t *surface_;
68
69 public:
70 AlphaSurface(unsigned int width,
71 unsigned int height)
72 {
73 surface_ = cairo_image_surface_create(CAIRO_FORMAT_A8, width, height);
74
75 if (!surface_)
76 {
77 // Should never occur
78 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
79 }
80
81 if (cairo_surface_status(surface_) != CAIRO_STATUS_SUCCESS)
82 {
83 LOG(ERROR) << "Cannot create a Cairo surface";
84 cairo_surface_destroy(surface_);
85 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
86 }
87 }
88
89 ~AlphaSurface()
90 {
91 cairo_surface_destroy(surface_);
92 }
93
94 void GetAccessor(Orthanc::ImageAccessor& target)
95 {
96 target.AssignWritable(Orthanc::PixelFormat_Grayscale8,
97 cairo_image_surface_get_width(surface_),
98 cairo_image_surface_get_height(surface_),
99 cairo_image_surface_get_stride(surface_),
100 cairo_image_surface_get_data(surface_));
101 }
102
103 void Blit(cairo_t* cr,
104 double x,
105 double y)
106 {
107 cairo_surface_mark_dirty(surface_);
108 cairo_mask_surface(cr, surface_, x, y);
109 cairo_fill(cr);
110 }
111 };
112
113
114 void CairoContext::DrawText(const Orthanc::Font& font,
115 const std::string& text,
116 double x,
117 double y,
118 BitmapAnchor anchor)
119 {
120 // Render a bitmap containing the text
121 unsigned int width, height;
122 font.ComputeTextExtent(width, height, text);
123
124 AlphaSurface surface(width, height);
125
126 Orthanc::ImageAccessor accessor;
127 surface.GetAccessor(accessor);
128 font.Draw(accessor, text, 0, 0, 255);
129
130 // Correct the text location given the anchor location
131 double deltaX, deltaY;
132 ComputeAnchorTranslation(deltaX, deltaY, anchor, width, height);
133
134 // Cancel zoom/rotation before blitting the text onto the surface
135 double pixelX = x;
136 double pixelY = y;
137 cairo_user_to_device(context_, &pixelX, &pixelY);
138
139 cairo_save(context_);
140 cairo_identity_matrix(context_);
141
142 // Blit the text bitmap
143 surface.Blit(context_, pixelX + deltaX, pixelY + deltaY);
144 cairo_restore(context_);
145 }
146 }