comparison OrthancStone/Sources/Fonts/FontRenderer.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Fonts/FontRenderer.cpp@28c64c246312
children 4fb8fdf03314
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
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-2020 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 "FontRenderer.h"
23
24 #include "../Toolbox/DynamicBitmap.h"
25
26 #include <OrthancException.h>
27
28
29 #include <ft2build.h>
30 #include FT_FREETYPE_H
31 #include FT_GLYPH_H
32
33
34 // https://stackoverflow.com/questions/31161284/how-can-i-get-the-corresponding-error-string-from-an-ft-error-code
35 static std::string GetErrorMessage(FT_Error err)
36 {
37 #undef __FTERRORS_H__
38 #define FT_ERRORDEF( e, v, s ) case e: return s;
39 #define FT_ERROR_START_LIST switch (err) {
40 #define FT_ERROR_END_LIST }
41 #include FT_ERRORS_H
42 return "(Unknown error)";
43 }
44
45
46 static void CheckError(FT_Error err)
47 {
48 if (err != 0)
49 {
50 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError,
51 "Error in FreeType: " + GetErrorMessage(err));
52 }
53 }
54
55
56 namespace OrthancStone
57 {
58 class FontRenderer::PImpl : public boost::noncopyable
59 {
60 private:
61 std::string fontContent_;
62 FT_Library library_;
63 FT_Face face_;
64
65 void Clear()
66 {
67 if (face_ != NULL)
68 {
69 FT_Done_Face(face_);
70 face_ = NULL;
71 }
72
73 fontContent_.clear();
74 }
75
76 public:
77 PImpl() :
78 library_(NULL),
79 face_(NULL)
80 {
81 CheckError(FT_Init_FreeType(&library_));
82 }
83
84
85 ~PImpl()
86 {
87 Clear();
88 FT_Done_FreeType(library_);
89 }
90
91
92 void LoadFont(const std::string& fontContent,
93 unsigned int fontSize)
94 {
95 Clear();
96
97 // It is necessary to make a private copy of the font, as
98 // Freetype makes the assumption that the buffer containing the
99 // font is never deleted
100 fontContent_.assign(fontContent);
101
102 const FT_Byte* data = reinterpret_cast<const FT_Byte*>(fontContent_.c_str());
103
104 CheckError(FT_New_Memory_Face(
105 library_, data, static_cast<FT_Long>(fontContent_.size()), 0, &face_));
106
107 CheckError(FT_Set_Char_Size(face_, // handle to face object
108 0, // char_width in 1/64th of points
109 fontSize * 64, // char_height in 1/64th of points
110 72, // horizontal device resolution
111 72)); // vertical device resolution
112
113 CheckError(FT_Select_Charmap(face_, FT_ENCODING_UNICODE));
114 }
115
116
117 Glyph* Render(uint32_t unicode)
118 {
119 if (face_ == NULL)
120 {
121 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls,
122 "First call LoadFont()");
123 }
124 else if (FT_Load_Char(face_, unicode, FT_LOAD_RENDER) != 0)
125 {
126 // This character is not available
127 return NULL;
128 }
129 else
130 {
131 if (face_->glyph->format != FT_GLYPH_FORMAT_BITMAP)
132 {
133 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
134 //CheckError(FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1));
135 }
136
137 Orthanc::ImageAccessor bitmap;
138 bitmap.AssignReadOnly(Orthanc::PixelFormat_Grayscale8,
139 face_->glyph->bitmap.width,
140 face_->glyph->bitmap.rows,
141 face_->glyph->bitmap.pitch,
142 face_->glyph->bitmap.buffer);
143
144 std::unique_ptr<Glyph> glyph(
145 new Glyph(bitmap.GetWidth(),
146 bitmap.GetHeight(),
147 face_->glyph->bitmap_left,
148 -face_->glyph->bitmap_top, // Positive for an upwards vertical distance
149 face_->glyph->advance.x >> 6,
150 face_->glyph->metrics.vertAdvance >> 6));
151
152 glyph->SetPayload(new DynamicBitmap(bitmap));
153
154 return glyph.release();
155 }
156 }
157 };
158
159
160
161 FontRenderer::FontRenderer() :
162 pimpl_(new PImpl)
163 {
164 }
165
166
167 void FontRenderer::LoadFont(const std::string& fontContent,
168 unsigned int fontSize)
169 {
170 pimpl_->LoadFont(fontContent, fontSize);
171 }
172
173
174 Glyph* FontRenderer::Render(uint32_t unicode)
175 {
176 return pimpl_->Render(unicode);
177 }
178 }