// // Copyright (c) 1993-2015 Robert McNeel & Associates. All rights reserved. // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert // McNeel & Associates. // // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF // MERCHANTABILITY ARE HEREBY DISCLAIMED. // // For complete openNURBS copyright information see . // //////////////////////////////////////////////////////////////// #include "opennurbs.h" #if !defined(ON_COMPILING_OPENNURBS) // This check is included in all opennurbs source .c and .cpp files to insure // ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. // When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined // and the opennurbs .h files alter what is declared and how it is declared. #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif ON_OBJECT_IMPLEMENT( ON_TextStyle, ON_ModelComponent, "4F0F51FB-35D0-4865-9998-6D2C6A99721D" ); const ON_TextStyle* ON_TextStyle::FromModelComponentRef( const class ON_ModelComponentReference& model_component_reference, const ON_TextStyle* none_return_value ) { const ON_TextStyle* p = ON_TextStyle::Cast(model_component_reference.ModelComponent()); return (nullptr != p) ? p : none_return_value; } ON_TextStyle::ON_TextStyle() : ON_ModelComponent(ON_ModelComponent::Type::TextStyle) {} ON_TextStyle::ON_TextStyle(const ON_TextStyle& src) : ON_ModelComponent(ON_ModelComponent::Type::TextStyle,src) { Internal_Copy(src); } ON_TextStyle& ON_TextStyle::operator=(const ON_TextStyle& src) { if (this != &src) { m_is_locked_bits = 0; ON_ModelComponent::operator=(src); Internal_Copy(src); } return *this; } void ON_TextStyle::Internal_Copy( const ON_TextStyle& src ) { m_managed_font = src.m_managed_font; m_font_description = src.m_font_description; m_is_set_bits = src.m_is_set_bits; // DO NOT COPY m_is_locked_bits. } // On September 24, 2015 the "V3" ON_Font was split into // ON_TextStyle (a document object) and // ON_Font (a current runtime resource) // Versions of opennurbs before ON_TextStyle::binary_archive_opennurbs_version // serialized ON_TextStyle information in the V5 ON_Font format. const unsigned int ON_TextStyle::binary_archive_opennurbs_version = ON_VersionNumberConstruct(6, 0, 2015, 9, 23, 0); bool ON_TextStyle::Write( ON_BinaryArchive& file // serialize definition to binary archive ) const { const ON_Font* font = (nullptr == m_managed_font || 0 == m_managed_font->RuntimeSerialNumber()) ? &ON_Font::Default : m_managed_font; if ( file.Archive3dmVersion() < 60 || file.ArchiveOpenNURBSVersion() < ON_TextStyle::binary_archive_opennurbs_version ) return font->WriteV5(Index(),Id(),file); if (!file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1)) return false; bool rc = false; for (;;) { if (!file.WriteModelComponentAttributes(*this,ON_ModelComponent::Attributes::BinaryArchiveAttributes)) break; // We only need to save the m_font_description when we are using an // alternate font or writing a V5 Mac file. const bool bWriteFont = (nullptr != m_managed_font); ON_wString postscript_name; ON_wString font_description; if (nullptr != m_managed_font) { postscript_name = m_managed_font->PostScriptName(); if (postscript_name.IsEmpty()) postscript_name = m_managed_font->Description(ON_Font::NameLocale::LocalizedFirst, ON_wString::HyphenMinus, 0, false); font_description = postscript_name; } else { font_description = m_font_description; } if (ON::RuntimeEnvironment::Apple == file.ArchiveRuntimeEnvironment() && m_apple_font_name.IsNotEmpty() && postscript_name.IsEmpty() ) { font_description = m_apple_font_name; } const bool bHaveFontDescription = font_description.IsNotEmpty(); if (!file.WriteBool(bHaveFontDescription)) break; if (bHaveFontDescription) { if (!file.WriteString(font_description)) break; } if (!file.WriteBool(bWriteFont)) break; if (bWriteFont) { if (!m_managed_font->Write(file)) break; } // version 1.1 added id and name if (!file.WriteUuid(Id())) break; if (!file.WriteString(Name())) break; rc = true; break; } if (!file.EndWrite3dmChunk() ) rc = false; return rc; } static void SetNameFromFontDescription( const ON_ComponentManifest& manifest, ON_TextStyle& text_style ) { const ON_wString font_description(text_style.Font().Description()); ON_wString text_style_name = manifest.UnusedName( text_style.ComponentType(), ON_nil_uuid, static_cast(font_description), nullptr, nullptr, 0, nullptr); text_style.SetName(text_style_name); } bool ON_TextStyle::Read( ON_BinaryArchive& file // restore definition from binary archive ) { ClearModelComponentAttributes(ON_ModelComponent::Attributes::AllAttributes); m_managed_font = nullptr; m_font_description = ON_wString::EmptyString; ON__UINT32 typecode = 0; ON__INT64 big_value = 0; if (file.Archive3dmVersion() < 60 || file.ArchiveOpenNURBSVersion() < ON_TextStyle::binary_archive_opennurbs_version // Sep 23, 215 had several in-house WIP versions and this makes the few files created // on that day read correctly || (file.ArchiveOpenNURBSVersion() < ON_VersionNumberConstruct(6, 0, 2015, 9, 24, 0) && file.PeekAt3dmBigChunkType(&typecode,&big_value) && TCODE_ANONYMOUS_CHUNK != typecode ) ) { ON_Font font; int V5_font_index = -1; ON_UUID V5_font_id = ON_nil_uuid; bool rc = font.ReadV5(file,&V5_font_index,&V5_font_id); SetFont(font.ManagedFont()); SetIndex(V5_font_index); if ( ON_nil_uuid == V5_font_id ) SetId(); else SetId(V5_font_id); // Use V5 font face name to set text style name. if (nullptr != m_managed_font) SetNameFromFontDescription(file.Manifest(),*this); return rc; } int major_version = 0; int minor_version = 0; if (!file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version)) return false; bool rc = false; for (;;) { unsigned int model_component_attributes_filter = 0; if (!file.ReadModelComponentAttributes(*this,&model_component_attributes_filter) ) break; // We only need to save the m_font_description when we are using an // alternate font. bool bHaveFontDescription = false; if (!file.ReadBool(&bHaveFontDescription)) break; ON_wString font_description; ON_wString apple_font_name; if (bHaveFontDescription) { if (!file.ReadString(font_description)) break; font_description.TrimLeftAndRight(); bHaveFontDescription = font_description.IsNotEmpty(); } if (ON::RuntimeEnvironment::Apple == file.ArchiveRuntimeEnvironment() && font_description.IsNotEmpty() && false == ON_Font::IsNotAppleFontName(font_description) ) { apple_font_name = font_description; } bool bReadFont = false; if (!file.ReadBool(&bReadFont)) break; if (bReadFont) { ON_Font font_characteristics; if (!font_characteristics.Read(file)) break; if (apple_font_name.IsEmpty()) apple_font_name = font_characteristics.PostScriptName(); SetFontFromDescription( static_cast(font_description), static_cast(apple_font_name), &font_characteristics ); } else { SetFontFromDescription( static_cast(font_description), static_cast(apple_font_name), nullptr ); } if (minor_version < 1) { // id and name were not saved in version 1.0 // They are required now and are created when an old file is read. SetId(); if (nullptr != m_managed_font) SetNameFromFontDescription(file.Manifest(),*this); rc = true; break; } // version 1.1 added id and name ON_UUID id; if (!file.ReadUuid(id)) break; SetId(id); ON_wString name; if (!file.ReadString(name)) break; SetName(name); rc = true; break; } if (!file.EndRead3dmChunk() ) rc = false; return rc; } void ON_TextStyle::ClearFont() { if (false == FontIsLocked()) { m_managed_font = nullptr; m_font_description = ON_wString::EmptyString; m_apple_font_name = ON_wString::EmptyString; m_is_set_bits &= ~ON_TextStyle::font_bit; IncrementContentVersionNumber(); } } bool ON_TextStyle::FontIsSet() const { return (0 != (m_is_set_bits & ON_TextStyle::font_bit)); } void ON_TextStyle::LockFont() { m_is_locked_bits |= ON_TextStyle::font_bit; } bool ON_TextStyle::FontIsLocked() const { return (0 != (m_is_locked_bits & ON_TextStyle::font_bit)); } void ON_TextStyle::SetFont( const ON_Font& font_characteristics ) { return SetFont(&font_characteristics); } void ON_TextStyle::SetFont( const ON_Font* font_characteristics ) { if (false == FontIsLocked()) { m_font_description = ON_wString::EmptyString; m_apple_font_name = ON_wString::EmptyString; m_managed_font = (nullptr == font_characteristics) ? nullptr : font_characteristics->ManagedFont(); if (nullptr == m_managed_font) { m_managed_font = &ON_Font::Default; } if (nullptr != font_characteristics) { m_font_description = font_characteristics->Description(); m_apple_font_name = font_characteristics->PostScriptName(); } if (m_font_description.IsEmpty()) m_font_description = m_managed_font->Description(); if (m_apple_font_name.IsEmpty()) m_apple_font_name = m_managed_font->PostScriptName(); m_is_set_bits |= ON_TextStyle::font_bit; IncrementContentVersionNumber(); } } void ON_TextStyle::SetFontFromDescription( const wchar_t* font_description, const wchar_t* apple_font_name, const ON_Font* alternate_font ) { ON_wString local_font_description(font_description); local_font_description.TrimLeftAndRight(); ON_wString local_apple_font_name(apple_font_name); local_apple_font_name.TrimLeftAndRight(); if (local_font_description.IsEmpty()) { SetFont(alternate_font); } else if (false == FontIsLocked()) { ON_Font font_characteristics; font_characteristics.SetFromFontDescription( static_cast(local_font_description), static_cast(local_apple_font_name) ); const ON_Font* managed_font = font_characteristics.ManagedFont(); if (nullptr == managed_font) { SetFont(alternate_font); } else { SetFont(managed_font); m_font_description = local_font_description; m_apple_font_name = local_apple_font_name; } unsigned char font_is_set_bit = 1; m_is_set_bits &= font_is_set_bit; IncrementContentVersionNumber(); } } bool ON_TextStyle::EqualTextStyleFontAndName( const ON_TextStyle& a, const ON_TextStyle& b ) { return ( a.Font().RuntimeSerialNumber() == b.Font().RuntimeSerialNumber() && a.m_font_description == b.m_font_description && ON_ModelComponent::CompareNameExact(a, b) ); } const wchar_t* ON_TextStyle::GetNameAndFontDescription( const wchar_t* sSeparator, ON_wString& name_and_font_description ) const { GetName(name_and_font_description); if ( FontIsSet() ) { ON_wString font_description = FontDescription(); if (font_description != name_and_font_description) { if (name_and_font_description.IsNotEmpty() && font_description.IsNotEmpty()) name_and_font_description += sSeparator; name_and_font_description += font_description; if (name_and_font_description.IsEmpty() || font_description.IsEmpty()) name_and_font_description.TrimLeftAndRight(); } } return static_cast(name_and_font_description); } const ON_Font& ON_TextStyle::Font() const { return (nullptr != m_managed_font && m_managed_font->IsManagedFont()) ? *m_managed_font : ON_Font::Default; } const ON_wString& ON_TextStyle::FontDescription() const { return m_font_description; } const wchar_t* ON_TextStyle::FontDescriptionAsPointer() const { return static_cast(m_font_description); } const ON_wString& ON_TextStyle::AppleFontName() const { return m_apple_font_name; } const wchar_t* ON_TextStyle::AppleFontNameAsPointer() const { return static_cast(m_apple_font_name); } bool ON_TextStyle::IsValid(ON_TextLog* text_log) const { return ( FontIsSet() && ON_ModelComponent::Type::TextStyle == ComponentType() && ON_ModelComponent::IsValid(text_log) && nullptr != m_managed_font && m_managed_font->IsManagedFont() && m_managed_font->IsValid() ); } void ON_TextStyle::Dump(ON_TextLog& dump) const { dump.Print("Text Style\n"); dump.PushIndent(); ON_ModelComponent::Dump(dump); dump.Print(L"Font = \"%ls\"\n", static_cast(m_font_description)); dump.PopIndent(); }