Mercurial > hg > orthanc-stone
diff Framework/Fonts/GlyphAlphabet.cpp @ 576:529c9617654b
FontRenderer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 19 Apr 2019 15:11:16 +0200 |
parents | |
children | 1091b2adeb5a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Fonts/GlyphAlphabet.cpp Fri Apr 19 15:11:16 2019 +0200 @@ -0,0 +1,170 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + + +#include "GlyphAlphabet.h" + +#include <Core/OrthancException.h> +#include <Core/Toolbox.h> + + +namespace OrthancStone +{ + void GlyphAlphabet::Clear() + { + for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) + { + assert(it->second != NULL); + delete it->second; + } + + content_.clear(); + lineHeight_ = 0; + } + + + void GlyphAlphabet::Register(uint32_t unicode, + const Glyph& glyph, + Orthanc::IDynamicObject* payload) + { + std::auto_ptr<Orthanc::IDynamicObject> protection(payload); + + // Don't add twice the same character + if (content_.find(unicode) == content_.end()) + { + std::auto_ptr<Glyph> raii(new Glyph(glyph)); + + if (payload != NULL) + { + raii->SetPayload(protection.release()); + } + + content_[unicode] = raii.release(); + + lineHeight_ = std::max(lineHeight_, glyph.GetLineHeight()); + } + } + + + void GlyphAlphabet::Register(FontRenderer& renderer, + uint32_t unicode) + { + std::auto_ptr<Glyph> glyph(renderer.Render(unicode)); + + if (glyph.get() != NULL) + { + Register(unicode, *glyph, glyph->ReleasePayload()); + } + } + + +#if ORTHANC_ENABLE_LOCALE == 1 + bool GlyphAlphabet::GetUnicodeFromCodepage(uint32_t& unicode, + unsigned int index, + Orthanc::Encoding encoding) + { + if (index > 255) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + std::string character; + character.resize(1); + character[0] = static_cast<unsigned char>(index); + + std::string utf8 = Orthanc::Toolbox::ConvertToUtf8(character, encoding, false /* no code extensions */); + + if (utf8.empty()) + { + // This character is not available in this codepage + return false; + } + else + { + size_t length; + Orthanc::Toolbox::Utf8ToUnicodeCharacter(unicode, length, utf8, 0); + assert(length != 0); + return true; + } + } +#endif + + + void GlyphAlphabet::Apply(IGlyphVisitor& visitor) const + { + for (Content::const_iterator it = content_.begin(); it != content_.end(); ++it) + { + assert(it->second != NULL); + visitor.Visit(it->first, *it->second); + } + } + + + void GlyphAlphabet::Apply(ITextVisitor& visitor, + const std::string& utf8) const + { + size_t pos = 0; + int x = 0; + int y = 0; + + while (pos < utf8.size()) + { + if (utf8[pos] == '\r') + { + // Ignore carriage return + pos++; + } + else if (utf8[pos] == '\n') + { + // This is a newline character + x = 0; + y += static_cast<int>(lineHeight_); + + pos++; + } + else + { + uint32_t unicode; + size_t length; + Orthanc::Toolbox::Utf8ToUnicodeCharacter(unicode, length, utf8, pos); + + Content::const_iterator glyph = content_.find(unicode); + + if (glyph != content_.end()) + { + assert(glyph->second != NULL); + const Orthanc::IDynamicObject* payload = + (glyph->second->HasPayload() ? &glyph->second->GetPayload() : NULL); + + visitor.Visit(unicode, + x + glyph->second->GetOffsetLeft(), + y + glyph->second->GetOffsetTop(), + glyph->second->GetWidth(), + glyph->second->GetHeight(), + payload); + x += glyph->second->GetAdvanceX(); + } + + assert(length != 0); + pos += length; + } + } + } +}