#include "StyleConverter.h" #include "../Common/WriterContext.h" #include "Transform.h" #include namespace HWP { #define DEFAULT_FONT_FAMILY std::wstring(L"Arial") #define DEFAULT_FONT_SIZE 18 #define DEFAULT_LANGUAGE std::wstring(L"en") #define DEFAULT_STYLE_NAME L"Style" #define DEFAULT_SPACING 240 #define SPACING_SCALE_MS_WORD 1.21 #define ADD_COLOR(r, g, b, enum_value) {{r, g, b}, enum_value} static const std::vector> s_arHighlightColors { ADD_COLOR( 0, 0, 0, EHighlightColors::Black), ADD_COLOR( 0, 0, 255, EHighlightColors::Blue), ADD_COLOR( 0, 255, 255, EHighlightColors::Cyan), ADD_COLOR( 0, 255, 0, EHighlightColors::Green), ADD_COLOR(255, 0, 255, EHighlightColors::Magenta), ADD_COLOR(255, 0, 0, EHighlightColors::Red), ADD_COLOR(255, 255, 0, EHighlightColors::Yellow), ADD_COLOR(255, 255, 255, EHighlightColors::White), ADD_COLOR( 0, 0, 139, EHighlightColors::DarkBlue), ADD_COLOR( 0, 139, 139, EHighlightColors::DarkCyan), ADD_COLOR( 0, 100, 0, EHighlightColors::DarkGreen), ADD_COLOR(139, 0, 139, EHighlightColors::DarkMagenta), ADD_COLOR(139, 0, 0, EHighlightColors::DarkRed), ADD_COLOR(128, 128, 0, EHighlightColors::DarkYellow), ADD_COLOR(169, 169, 169, EHighlightColors::DarkGray), ADD_COLOR(211, 211, 211, EHighlightColors::LightGray) }; CStyleConverter::CStyleConverter() : m_ushLastParaShapeId(0), m_ushLastCharShapeId(0) { m_mUsedStyleNames.insert(std::make_pair(DEFAULT_STYLE_NAME, 0)); } std::wstring CStyleConverter::CreateStyle(short shParaShapeId, short shParaStyleId, CWriterContext& oContext, TConversionState& oState) { std::map::const_iterator itFound = m_mUsedStyles.find(shParaStyleId); if (m_mUsedStyles.cend() != itFound) return itFound->second; const CHWPRecordStyle *pParaStyle = dynamic_cast(oContext.GetParaStyle(shParaStyleId)); if (nullptr == pParaStyle) return std::wstring(); const CHWPRecordParaShape* pParaShapeRecord = dynamic_cast(oContext.GetParaShape(pParaStyle->GetParaShapeId())); if (nullptr == pParaShapeRecord) return std::wstring(); std::wstring wsParaStyleName = !pParaStyle->GetEngName().empty() ? pParaStyle->GetEngName() : pParaStyle->GetName(); if (wsParaStyleName.empty()) wsParaStyleName = DEFAULT_STYLE_NAME; const std::wstring wsStyleName = GenerateUniqueID(wsParaStyleName); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); WriteParagraphProperties(GenerateParagraphStyle(*pParaShapeRecord), m_oStylesXml); m_oStylesXml.WriteString(L""); const CHWPRecordCharShape *pCharShapeRecord = dynamic_cast(oContext.GetCharShape(pParaStyle->GetCharShapeId())); if (nullptr != pCharShapeRecord) { m_oStylesXml.WriteString(L""); WriteRunnerProperties(GenerateRunnerStyle(*pCharShapeRecord), m_oStylesXml); m_oStylesXml.WriteString(L""); } m_oStylesXml.WriteString(L""); m_mUsedStyles.insert(std::make_pair(shParaStyleId, wsStyleName)); m_ushLastParaShapeId = pParaStyle->GetParaShapeId(); m_ushLastCharShapeId = pParaStyle->GetCharShapeId(); return wsStyleName; } bool CStyleConverter::WriteDifferenceParagraphStyles(short shFirtsParaShapeId, short shSecondParaShapeId, CWriterContext& oContext, NSStringUtils::CStringBuilder& oBuilder) { const CHWPRecordParaShape* pFirstParaShape = dynamic_cast(oContext.GetParaShape(shFirtsParaShapeId)); if (nullptr == pFirstParaShape) return false; const CHWPRecordParaShape* pSecondParaShape = dynamic_cast(oContext.GetParaShape(shSecondParaShapeId)); if (nullptr == pSecondParaShape) return false; CParagraphsStyle oFirstParagraphStyle {GenerateParagraphStyle(*pFirstParaShape )}; CParagraphsStyle oSecondParagraphStyle{GenerateParagraphStyle(*pSecondParaShape)}; oSecondParagraphStyle -= oFirstParagraphStyle; WriteParagraphProperties(oSecondParagraphStyle, oBuilder); return true; } bool CStyleConverter::WriteDifferenceRunnerStyles(short shFirtsCharShapeId, short shSecondCharShapeId, CWriterContext& oContext, NSStringUtils::CStringBuilder& oBuilder) { const CHWPRecordCharShape* pFirstCharShape = dynamic_cast(oContext.GetCharShape(shFirtsCharShapeId)); if (nullptr == pFirstCharShape) return false; const CHWPRecordCharShape* pSecondCharShape = dynamic_cast(oContext.GetCharShape(shSecondCharShapeId)); if (nullptr == pSecondCharShape) return false; CRunnerStyle oFirstRunnerStyle {GenerateRunnerStyle(*pFirstCharShape )}; CRunnerStyle oSecondRunnerStyle{GenerateRunnerStyle(*pSecondCharShape)}; oSecondRunnerStyle -= oFirstRunnerStyle; WriteRunnerProperties(oSecondRunnerStyle, oBuilder); return true; } unsigned short CStyleConverter::GetLastParaShapeId() const { return m_ushLastParaShapeId; } unsigned short CStyleConverter::GetLastCharShapeId() const { return m_ushLastCharShapeId; } std::wstring CStyleConverter::GenerateUniqueID(const std::wstring& wsName) { std::unordered_map::const_iterator itFound = m_mUsedStyleNames.find(wsName); if (itFound == m_mUsedStyleNames.cend()) { m_mUsedStyleNames.insert(std::make_pair(wsName, 0)); return wsName; } return wsName + std::to_wstring(++m_mUsedStyleNames[wsName]); } CParagraphsStyle CStyleConverter::GenerateParagraphStyle(const CHWPRecordParaShape& oParaShape) { CParagraphsStyle oParagraphsStyle; if (oParaShape.KeepWithNext()) oParagraphsStyle.SetKeepNext(true); oParagraphsStyle.SetFirstLine(oParaShape.GetIndent()); oParagraphsStyle.SetLeftInd(oParaShape.GetLeftIndent()); oParagraphsStyle.SetRightInd(oParaShape.GetRightIndent()); switch(oParaShape.GetHorizantalAlign()) { case EHorizontalAlign::JUSTIFY: oParagraphsStyle.SetJs(EJs::Both); break; case EHorizontalAlign::LEFT: oParagraphsStyle.SetJs(EJs::Left); break; case EHorizontalAlign::RIGHT: oParagraphsStyle.SetJs(EJs::Right); break; case EHorizontalAlign::CENTER: oParagraphsStyle.SetJs(EJs::Center); break; case EHorizontalAlign::DISTRIBUTE: case EHorizontalAlign::DISTRIBUTE_SPACE: oParagraphsStyle.SetJs(EJs::Distribute); break; } switch(oParaShape.GetVerticalAlign()) { case EVerticalAlign::BOTTOM: oParagraphsStyle.SetTextAlignment(ETextAlignment::Bottom); break; case EVerticalAlign::TOP:oParagraphsStyle.SetTextAlignment(ETextAlignment::Top); break; case EVerticalAlign::CENTER: oParagraphsStyle.SetTextAlignment(ETextAlignment::Center); break; case EVerticalAlign::BASELINE: break; } switch(oParaShape.GetLineSpacingType()) { case 0x0: { oParagraphsStyle.SetSpacingLineRule(ELineRule::Auto); oParagraphsStyle.SetSpacing(static_cast(2.4 * (double)oParaShape.GetLineSpacing())); // 240 / 100 break; } case 0x01: { oParagraphsStyle.SetSpacingLineRule(ELineRule::Exact); oParagraphsStyle.SetSpacing(static_cast((double)oParaShape.GetLineSpacing() / 10.)); /*0.352778*/; //(1pt=0.352778mm) //TODO:: проверить, как найдется пример break; } case 0x02: case 0x03: { oParagraphsStyle.SetSpacingLineRule(ELineRule::AtLeast); oParagraphsStyle.SetSpacing(static_cast((double)oParaShape.GetLineSpacing() / 10.)); //TODO:: проверить, как найдется пример break; } default: break; } if (0 != oParaShape.GetMarginPrev()) oParagraphsStyle.SetSpacingBefore(static_cast((double)oParaShape.GetMarginPrev() / 10.)); if (0 != oParaShape.GetMarginNext()) oParagraphsStyle.SetSpacingAfter(static_cast((double)oParaShape.GetMarginNext() / 10.)); return oParagraphsStyle; } CRunnerStyle CStyleConverter::GenerateRunnerStyle(const CHWPRecordCharShape& oCharShape) { CRunnerStyle oRunnerStyle; oRunnerStyle.SetAscii(oCharShape.GetFontName(ELang::LATIN)); oRunnerStyle.SetEastAsia(oCharShape.GetFontName(ELang::HANGUL)); oRunnerStyle.SetRatio(oCharShape.GetRatio(ELang::LATIN)); oRunnerStyle.SetSpacing(static_cast((double)oCharShape.GetSpacing(ELang::LATIN) * SPACING_SCALE_MS_WORD)); if (oCharShape.Bold()) oRunnerStyle.SetBold(true); if (oCharShape.Italic()) oRunnerStyle.SetItalic(true); if (oCharShape.StrikeOut() && ELineStyle2::NONE != oCharShape.GetStrikeOutType()) oRunnerStyle.SetStrike(EStrikeType::Single); if (oCharShape.SuperScript()) oRunnerStyle.SetVerticalAlign(EVerticalAlignRun::Superscript); else if (oCharShape.SubScript()) oRunnerStyle.SetVerticalAlign(EVerticalAlignRun::Subscript); const int nHeight = static_cast(((double)(std::abs)(oCharShape.GetHeight()) * ((double)oCharShape.GetRelSize(ELang::HANGUL) / 100.) / 100.) * 2.); oRunnerStyle.SetSz(nHeight); oRunnerStyle.SetColor(oCharShape.GetTextColor()); if (oCharShape.Underline()) { EUnderline eUnderlineType = oCharShape.GetUnderlineType(); ELineStyle1 eUnderlineStyle = oCharShape.GetUnderlineStyle(); if (EUnderline::BOTTOM == eUnderlineType) { switch (eUnderlineStyle) { case ELineStyle1::SOLID: oRunnerStyle.SetU({EUType::Single, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DASH: oRunnerStyle.SetU({EUType::Dash, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DOT: oRunnerStyle.SetU({EUType::Dotted, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DASH_DOT: oRunnerStyle.SetU({EUType::DotDash, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DASH_DOT_DOT: oRunnerStyle.SetU({EUType::DotDotDash, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::LONG_DASH: oRunnerStyle.SetU({EUType::DotDash, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::CIRCLE: oRunnerStyle.SetU({EUType::Dotted, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DOUBLE_SLIM: case ELineStyle1::SLIM_THICK: case ELineStyle1::THICK_SLIM: case ELineStyle1::SLIM_THICK_SLIM: oRunnerStyle.SetU({EUType::Double, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::WAVE: oRunnerStyle.SetU({EUType::Wave, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::DOUBLE_WAVE: oRunnerStyle.SetU({EUType::WavyDouble, oCharShape.GetUnderlineColor()}); break; case ELineStyle1::THICK_3D: case ELineStyle1::THICK_3D_REVERS_LI: case ELineStyle1::SOLID_3D: case ELineStyle1::SOLID_3D_REVERS_LI: oRunnerStyle.SetU({EUType::Thick, oCharShape.GetUnderlineColor()}); break; } } else if (EUnderline::CENTER == eUnderlineType && !oCharShape.StrikeOut()) { if (eUnderlineStyle == ELineStyle1::DOUBLE_SLIM || eUnderlineStyle == ELineStyle1::DOUBLE_WAVE) oRunnerStyle.SetStrike(EStrikeType::Double); else oRunnerStyle.SetStrike(EStrikeType::Single); } } if (0xFFFFFFFF != oCharShape.GetShadeColor()) oRunnerStyle.SetShadeColor(oCharShape.GetShadeColor()); return oRunnerStyle; } void CStyleConverter::WriteParagraphProperties(const CParagraphsStyle& oParagraphsStyle, NSStringUtils::CStringBuilder& oBuilder) { if (oParagraphsStyle.Empty()) return; if (oParagraphsStyle.KeepNextIsSet() && oParagraphsStyle.KeepNext()) oBuilder.WriteString(L""); if ((oParagraphsStyle.FirstLineIsSet() && 0 != oParagraphsStyle.GetFirstLine()) || (oParagraphsStyle.LeftIndIsSet() && 0 != oParagraphsStyle.GetLeftInd()) || (oParagraphsStyle.RightIndIsSet() && 0 != oParagraphsStyle.GetRightInd())) { oBuilder.WriteString(L" 0) { oBuilder.WriteString(L" w:firstLine=\"" + std::to_wstring(static_cast(std::round(oParagraphsStyle.GetFirstLine() / 10.))) + L"\""); if (0 != nLeftInd) oBuilder.WriteString(L" w:left=\"" + std::to_wstring(static_cast(std::round(nLeftInd / 10.))) + L"\""); } else { const int nHanging{static_cast(std::round(-oParagraphsStyle.GetFirstLine() / 10.))}; oBuilder.WriteString(L" w:hanging=\"" + std::to_wstring(nHanging) + L"\""); oBuilder.WriteString(L" w:left=\"" + std::to_wstring(static_cast(std::round(nLeftInd / 10.)) + nHanging) + L"\""); } } else if (0 != nLeftInd) oBuilder.WriteString(L" w:left=\"" + std::to_wstring(static_cast(std::round(oParagraphsStyle.GetLeftInd() / 10.))) + L"\""); if (oParagraphsStyle.RightIndIsSet() && 0 != oParagraphsStyle.GetRightInd()) oBuilder.WriteString(L" w:right=\"" + std::to_wstring(static_cast(std::round(oParagraphsStyle.GetRightInd() / 10.))) + L"\""); oBuilder.WriteString(L"/>"); } if (oParagraphsStyle.JsIsSet()) { switch(oParagraphsStyle.GetJs()) { case EJs::Left: oBuilder.WriteString(L""); break; case EJs::Center: oBuilder.WriteString(L""); break; case EJs::Right: oBuilder.WriteString(L""); break; case EJs::Both: oBuilder.WriteString(L""); break; case EJs::Distribute:oBuilder.WriteString(L""); break; } } if (oParagraphsStyle.TextAlignmentIsSet()) { switch(oParagraphsStyle.GetTextAlignment()) { case ETextAlignment::Top: oBuilder.WriteString(L""); break; case ETextAlignment::Center: oBuilder.WriteString(L""); break; case ETextAlignment::Bottom: oBuilder.WriteString(L""); break; } } if (oParagraphsStyle.SpacingLineRuleIsSet() || oParagraphsStyle.SpacingIsSet() || oParagraphsStyle.SpacingBeforeIsSet() || oParagraphsStyle.SpacingAfterIsSet()) { oBuilder.WriteString(L""); } } void CStyleConverter::WriteParagraphsStyle(const CParagraphsStyle& oParagraphsStyle, const std::wstring& wsName, const std::wstring& wsLink, NSStringUtils::CStringBuilder& oBuilder) { oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); WriteParagraphProperties(oParagraphsStyle, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); } void CStyleConverter::WriteRunnerProperties(const CRunnerStyle& oRunnerStyle, NSStringUtils::CStringBuilder& oBuilder) { if (oRunnerStyle.Empty()) return; std::wstring wsAScii, wsEastAsia; if (oRunnerStyle.AsciiIsSet()) wsAScii = oRunnerStyle.GetAscii(); if (oRunnerStyle.EastAsiaIsSet()) wsEastAsia = oRunnerStyle.GetEastAsia(); if (!wsAScii.empty() || !wsEastAsia.empty()) { oBuilder.WriteString(L""); } if (oRunnerStyle.BoldIsSet() && oRunnerStyle.Bold()) oBuilder.WriteString(L""); if (oRunnerStyle.ItalicIsSet() && oRunnerStyle.Italic()) oBuilder.WriteString(L""); if (oRunnerStyle.SzIsSet()) oBuilder.WriteString(L""); if (oRunnerStyle.ColorIsSet()) oBuilder.WriteString(L""); if (oRunnerStyle.RatioIsSet() && 100 != oRunnerStyle.GetRatio()) oBuilder.WriteString(L""); if (oRunnerStyle.SpacingIsSet() && 0 != oRunnerStyle.GetSpacing()) oBuilder.WriteString(L""); if (oRunnerStyle.UIsSet()) { oBuilder.WriteString(L""); } if (oRunnerStyle.StrikeIsSet()) { switch (oRunnerStyle.GetStrike()) { case EStrikeType::Single: oBuilder.WriteString(L""); break; case EStrikeType::Double: oBuilder.WriteString(L""); break; } } if (oRunnerStyle.HighlightIsSet()) { oBuilder.WriteString(L""); } if (oRunnerStyle.ShadeColorIsSet()) oBuilder.WriteString(L""); if (oRunnerStyle.VerticalAlignIsSet()) { switch (oRunnerStyle.GetVerticalAlign()) { case EVerticalAlignRun::Baseline: break; case EVerticalAlignRun::Superscript: oBuilder.WriteString(L""); break; case EVerticalAlignRun::Subscript: oBuilder.WriteString(L""); break; } } } void CStyleConverter::WriteRunnerStyle(const CRunnerStyle& oRunnerStyle, const std::wstring& wsName, const std::wstring& wsLink, NSStringUtils::CStringBuilder& oBuilder) { oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); WriteRunnerProperties(oRunnerStyle, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); } bool CStyleConverter::SaveToFile(const std::wstring& wsDirectory) { NSFile::CFileBinary oStylesWriter; if (!oStylesWriter.CreateFileW(wsDirectory + L"styles.xml")) return false; oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(L""); oStylesWriter.WriteStringUTF8(m_oStylesXml.GetData()); oStylesWriter.WriteStringUTF8(L""); return true; } CParagraphsStyle::CParagraphsStyle() {} CParagraphsStyle& CParagraphsStyle::operator-=(const CParagraphsStyle& oParagraphStyle) { if (Empty() || oParagraphStyle.Empty()) return *this; m_bKeepNext -= oParagraphStyle.m_bKeepNext; m_oInd -= oParagraphStyle.m_oInd; m_eJs -= oParagraphStyle.m_eJs; m_eTextAlignment -= oParagraphStyle.m_eTextAlignment; m_oSpacing -= oParagraphStyle.m_oSpacing; return *this; } void CParagraphsStyle::Clear() { m_bKeepNext.UnSet(); m_eJs.UnSet(); m_eTextAlignment.UnSet(); m_oInd.m_nFirstLine.UnSet(); m_oInd.m_nLeft.UnSet(); m_oInd.m_nRight.UnSet(); m_oSpacing.m_eLineRule.UnSet(); m_oSpacing.m_nLine.UnSet(); m_oSpacing.m_nAfter.UnSet(); m_oSpacing.m_nBefore.UnSet(); } bool CParagraphsStyle::Empty() const { return !m_bKeepNext.IsSet() && !m_oInd.m_nFirstLine.IsSet() && !m_oInd.m_nLeft.IsSet() && !m_oInd.m_nRight.IsSet() && !m_eJs.IsSet() && !m_eTextAlignment.IsSet() && !m_oSpacing.m_eLineRule.IsSet() && !m_oSpacing.m_nLine.IsSet() && !m_oSpacing.m_nAfter.IsSet() && !m_oSpacing.m_nBefore.IsSet(); } #define CREATE_BODY_METHODS_FOR_PROPERTY(class_name, type, name, variable_name)\ void class_name::Set##name(type oValue)\ {\ variable_name = oValue;\ }\ bool class_name::name##IsSet() const\ {\ return variable_name.IsSet();\ }\ type class_name::Get##name() const\ {\ return variable_name;\ } #define CREATE_BODY_METHODS_FOR_PROPERTY_BOOL(class_name, name, variable_name)\ void class_name::Set##name(bool oValue)\ {\ variable_name = oValue;\ }\ bool class_name::name##IsSet() const\ {\ return variable_name.IsSet();\ }\ bool class_name::name() const\ {\ return variable_name;\ } CREATE_BODY_METHODS_FOR_PROPERTY_BOOL(CParagraphsStyle, KeepNext, m_bKeepNext) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, FirstLine, m_oInd.m_nFirstLine) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, LeftInd, m_oInd.m_nLeft) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, RightInd, m_oInd.m_nRight) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, EJs, Js, m_eJs) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, ETextAlignment, TextAlignment, m_eTextAlignment) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, ELineRule, SpacingLineRule, m_oSpacing.m_eLineRule) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, Spacing, m_oSpacing.m_nLine) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, SpacingBefore, m_oSpacing.m_nBefore) CREATE_BODY_METHODS_FOR_PROPERTY(CParagraphsStyle, int, SpacingAfter, m_oSpacing.m_nAfter) template CProperty::CProperty() : m_bIsSet(false) {} template void CProperty::UnSet() { m_bIsSet = false; } template void CProperty::SetValue(T oValue) { m_oValue = oValue; m_bIsSet = true; } template bool CProperty::IsSet() const { return m_bIsSet; } template T CProperty::GetValue() const { return m_oValue; } template CProperty& CProperty::operator=(T oValue) { SetValue(oValue); return *this; } template CProperty& CProperty::operator-=(const CProperty& oProperty) { if (!m_bIsSet || !oProperty.m_bIsSet || m_oValue != oProperty.m_oValue) return *this; m_bIsSet = false; return *this; } template CProperty::operator T() const { return m_oValue; } TRFonts& TRFonts::operator-=(const TRFonts& oRFonts) { m_wsAscii -= oRFonts.m_wsAscii; m_wsEastAsia -= oRFonts.m_wsEastAsia; return *this; } CRunnerStyle::CRunnerStyle() {} CRunnerStyle& CRunnerStyle::operator-=(const CRunnerStyle& oRunnerStyle) { m_oRFonts -= oRunnerStyle.m_oRFonts; m_bBold -= oRunnerStyle.m_bBold; m_bItalic -= oRunnerStyle.m_bItalic; m_nSz -= oRunnerStyle.m_nSz; m_oColor -= oRunnerStyle.m_oColor; m_nShadeColor -= oRunnerStyle.m_nShadeColor; m_shRatio -= oRunnerStyle.m_shRatio; m_oU -= oRunnerStyle.m_oU; m_eStrike -= oRunnerStyle.m_eStrike; m_shSpacing -= oRunnerStyle.m_shSpacing; m_oHighlight -= oRunnerStyle.m_oHighlight; m_eVerticalAlign -= oRunnerStyle.m_eVerticalAlign; return *this; } void CRunnerStyle::Clear() { m_oRFonts.m_wsAscii.UnSet(); m_oRFonts.m_wsEastAsia.UnSet(); m_bBold.UnSet(); m_bItalic.UnSet(); m_nSz.UnSet(); m_oColor.UnSet(); m_nShadeColor.UnSet(); m_shRatio.UnSet(); m_oU.UnSet(); m_eStrike.UnSet(); m_shSpacing.UnSet(); m_oHighlight.UnSet(); m_eVerticalAlign.UnSet(); } bool CRunnerStyle::Empty() const { return !m_oRFonts.m_wsAscii.IsSet() && !m_oRFonts.m_wsEastAsia.IsSet() && !m_bBold.IsSet() && !m_bItalic.IsSet() && !m_nSz.IsSet() && !m_oColor.IsSet() && !m_nShadeColor.IsSet() && !m_shRatio.IsSet() && !m_oU.IsSet() && !m_eStrike.IsSet() && !m_shSpacing.IsSet() && !m_oHighlight.IsSet() && !m_eVerticalAlign.IsSet(); } CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, std::wstring, Ascii, m_oRFonts.m_wsAscii); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, std::wstring, EastAsia, m_oRFonts.m_wsEastAsia); CREATE_BODY_METHODS_FOR_PROPERTY_BOOL(CRunnerStyle, Bold, m_bBold); CREATE_BODY_METHODS_FOR_PROPERTY_BOOL(CRunnerStyle, Italic, m_bItalic); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, int, Sz, m_nSz); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, TColor, Color, m_oColor); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, int, ShadeColor, m_nShadeColor) CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, short, Ratio, m_shRatio) CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, TU, U, m_oU); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, EStrikeType, Strike, m_eStrike); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, short, Spacing, m_shSpacing); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, EHighlightColors, Highlight, m_oHighlight); CREATE_BODY_METHODS_FOR_PROPERTY(CRunnerStyle, EVerticalAlignRun, VerticalAlign, m_eVerticalAlign); bool TU::operator!=(const TU& oU) const { return m_eVal != oU.m_eVal || m_oColor != oU.m_oColor; } EHighlightColors NormalizeHighlightColor(const TColor& oCurrentColor) { EHighlightColors eSelectedColor{EHighlightColors::Yellow}; double dMinDistance = 999.; double dDistance; for (const std::pair& oColor : s_arHighlightColors) { dDistance = sqrt(pow(oCurrentColor.m_uchRed - oColor.first.m_uchRed, 2) + pow(oCurrentColor.m_uchGreen - oColor.first.m_uchGreen, 2) + pow(oCurrentColor.m_uchBlue - oColor.first.m_uchBlue, 2)); if (dDistance < dMinDistance) { dMinDistance = dDistance; eSelectedColor = oColor.second; } } return eSelectedColor; } TLineSpacing& TLineSpacing::operator-=(const TLineSpacing& oLineSpacing) { m_eLineRule -= oLineSpacing.m_eLineRule; m_nLine -= oLineSpacing.m_nLine; m_nAfter -= oLineSpacing.m_nAfter; m_nBefore -= oLineSpacing.m_nBefore; return *this; } TInd& TInd::operator-=(const TInd& oInd) { m_nFirstLine -= oInd.m_nFirstLine; m_nLeft -= oInd.m_nLeft; m_nRight -= oInd.m_nRight; return *this; } }