Mercurial > hg > orthanc-stone
annotate Framework/Fonts/FontRenderer.cpp @ 1186:3284c3fd96ad broker
merge
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 22 Nov 2019 09:51:47 +0100 |
parents | 9a474e90e832 |
children | 2d8ab34c8c91 |
rev | line source |
---|---|
576 | 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 "FontRenderer.h" | |
23 | |
24 #include "../Toolbox/DynamicBitmap.h" | |
25 | |
26 #include <Core/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 | |
693
9a474e90e832
Fixed a bunch of truncation warnings in various parts of the library
Benjamin Golinvaux <bgo@osimis.io>
parents:
576
diff
changeset
|
104 CheckError(FT_New_Memory_Face( |
9a474e90e832
Fixed a bunch of truncation warnings in various parts of the library
Benjamin Golinvaux <bgo@osimis.io>
parents:
576
diff
changeset
|
105 library_, data, static_cast<FT_Long>(fontContent_.size()), 0, &face_)); |
9a474e90e832
Fixed a bunch of truncation warnings in various parts of the library
Benjamin Golinvaux <bgo@osimis.io>
parents:
576
diff
changeset
|
106 |
576 | 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::auto_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 void FontRenderer::LoadFont(Orthanc::EmbeddedResources::FileResourceId resource, | |
175 unsigned int fontSize) | |
176 { | |
177 std::string content; | |
178 Orthanc::EmbeddedResources::GetFileResource(content, resource); | |
179 LoadFont(content, fontSize); | |
180 } | |
181 | |
182 | |
183 Glyph* FontRenderer::Render(uint32_t unicode) | |
184 { | |
185 return pimpl_->Render(unicode); | |
186 } | |
187 } |