| OLD | NEW |
| 1 // Copyright 2015 PDFium Authors. All rights reserved. | 1 // Copyright 2015 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "xfa/fgas/font/cfgas_fontmgr.h" | 7 #include "xfa/fgas/font/cfgas_fontmgr.h" |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "core/fxcrt/fx_stream.h" | 12 #include "core/fxcrt/fx_stream.h" |
| 13 #include "core/fxge/cfx_fontmapper.h" | 13 #include "core/fxge/cfx_fontmapper.h" |
| 14 #include "core/fxge/cfx_fontmgr.h" | 14 #include "core/fxge/cfx_fontmgr.h" |
| 15 #include "core/fxge/cfx_gemodule.h" | 15 #include "core/fxge/cfx_gemodule.h" |
| 16 #include "core/fxge/ifx_systemfontinfo.h" | 16 #include "core/fxge/ifx_systemfontinfo.h" |
| 17 #include "third_party/base/ptr_util.h" | 17 #include "third_party/base/ptr_util.h" |
| 18 #include "third_party/base/stl_util.h" |
| 18 #include "xfa/fgas/crt/fgas_codepage.h" | 19 #include "xfa/fgas/crt/fgas_codepage.h" |
| 19 #include "xfa/fgas/font/cfgas_gefont.h" | 20 #include "xfa/fgas/font/cfgas_gefont.h" |
| 20 #include "xfa/fgas/font/fgas_fontutils.h" | 21 #include "xfa/fgas/font/fgas_fontutils.h" |
| 21 | 22 |
| 22 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 23 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 int32_t GetSimilarityScore(FX_FONTDESCRIPTOR const* pFont, | 27 int32_t GetSimilarityScore(FX_FONTDESCRIPTOR const* pFont, |
| 27 uint32_t dwFontStyles) { | 28 uint32_t dwFontStyles) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 } | 95 } |
| 95 | 96 |
| 96 } // namespace | 97 } // namespace |
| 97 | 98 |
| 98 std::unique_ptr<CFGAS_FontMgr> CFGAS_FontMgr::Create( | 99 std::unique_ptr<CFGAS_FontMgr> CFGAS_FontMgr::Create( |
| 99 FX_LPEnumAllFonts pEnumerator) { | 100 FX_LPEnumAllFonts pEnumerator) { |
| 100 return pdfium::MakeUnique<CFGAS_FontMgr>(pEnumerator); | 101 return pdfium::MakeUnique<CFGAS_FontMgr>(pEnumerator); |
| 101 } | 102 } |
| 102 | 103 |
| 103 CFGAS_FontMgr::CFGAS_FontMgr(FX_LPEnumAllFonts pEnumerator) | 104 CFGAS_FontMgr::CFGAS_FontMgr(FX_LPEnumAllFonts pEnumerator) |
| 104 : m_pEnumerator(pEnumerator), | 105 : m_pEnumerator(pEnumerator), m_FontFaces(100) { |
| 105 m_FontFaces(100), | |
| 106 m_CPFonts(8), | |
| 107 m_FamilyFonts(16), | |
| 108 m_UnicodeFonts(16), | |
| 109 m_BufferFonts(4), | |
| 110 m_StreamFonts(4), | |
| 111 m_DeriveFonts(4) { | |
| 112 if (m_pEnumerator) | 106 if (m_pEnumerator) |
| 113 m_pEnumerator(m_FontFaces, nullptr, 0xFEFF); | 107 m_pEnumerator(m_FontFaces, nullptr, 0xFEFF); |
| 114 } | 108 } |
| 115 | 109 |
| 116 CFGAS_FontMgr::~CFGAS_FontMgr() { | 110 CFGAS_FontMgr::~CFGAS_FontMgr() { |
| 117 m_FontFaces.RemoveAll(false); | 111 m_FontFaces.RemoveAll(false); |
| 118 m_CPFonts.RemoveAll(); | |
| 119 m_FamilyFonts.RemoveAll(); | |
| 120 m_UnicodeFonts.RemoveAll(); | |
| 121 m_BufferFonts.RemoveAll(); | |
| 122 m_StreamFonts.RemoveAll(); | |
| 123 m_DeriveFonts.RemoveAll(); | |
| 124 for (int32_t i = m_Fonts.GetUpperBound(); i >= 0; i--) | |
| 125 m_Fonts[i]->Release(); | |
| 126 } | 112 } |
| 127 | 113 |
| 128 CFGAS_GEFont* CFGAS_FontMgr::GetFontByCodePage(uint16_t wCodePage, | 114 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage( |
| 129 uint32_t dwFontStyles, | 115 uint16_t wCodePage, |
| 130 const FX_WCHAR* pszFontFamily) { | 116 uint32_t dwFontStyles, |
| 117 const FX_WCHAR* pszFontFamily) { |
| 131 uint32_t dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); | 118 uint32_t dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); |
| 132 CFGAS_GEFont* pFont = nullptr; | 119 auto it = m_CPFonts.find(dwHash); |
| 133 if (m_CPFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) | 120 if (it != m_CPFonts.end()) { |
| 134 return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : nullptr; | 121 return it->second ? LoadFont(it->second, dwFontStyles, wCodePage) : nullptr; |
| 135 FX_FONTDESCRIPTOR const* pFD = | 122 } |
| 123 const FX_FONTDESCRIPTOR* pFD = |
| 136 FindFont(pszFontFamily, dwFontStyles, true, wCodePage); | 124 FindFont(pszFontFamily, dwFontStyles, true, wCodePage); |
| 137 if (!pFD) | 125 if (!pFD) |
| 138 pFD = FindFont(nullptr, dwFontStyles, true, wCodePage); | 126 pFD = FindFont(nullptr, dwFontStyles, true, wCodePage); |
| 139 if (!pFD) | 127 if (!pFD) |
| 140 pFD = FindFont(nullptr, dwFontStyles, false, wCodePage); | 128 pFD = FindFont(nullptr, dwFontStyles, false, wCodePage); |
| 141 if (!pFD) | 129 if (!pFD) |
| 142 return nullptr; | 130 return nullptr; |
| 143 | 131 |
| 144 pFont = | 132 CFX_RetainPtr<CFGAS_GEFont> pFont = |
| 145 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); | 133 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); |
| 146 if (!pFont) | 134 if (!pFont) |
| 147 return nullptr; | 135 return nullptr; |
| 148 | 136 |
| 149 m_Fonts.Add(pFont); | 137 m_Fonts.push_back(pFont); |
| 150 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 138 m_CPFonts[dwHash] = pFont; |
| 151 dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage); | 139 dwHash = FGAS_GetFontFamilyHash(pFD->wsFontFace, dwFontStyles, wCodePage); |
| 152 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 140 m_FamilyFonts[dwHash] = pFont; |
| 153 return LoadFont(pFont, dwFontStyles, wCodePage); | 141 return LoadFont(pFont, dwFontStyles, wCodePage); |
| 154 } | 142 } |
| 155 | 143 |
| 156 CFGAS_GEFont* CFGAS_FontMgr::GetFontByUnicode(FX_WCHAR wUnicode, | 144 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode( |
| 157 uint32_t dwFontStyles, | 145 FX_WCHAR wUnicode, |
| 158 const FX_WCHAR* pszFontFamily) { | 146 uint32_t dwFontStyles, |
| 147 const FX_WCHAR* pszFontFamily) { |
| 159 const FGAS_FONTUSB* pRet = FGAS_GetUnicodeBitField(wUnicode); | 148 const FGAS_FONTUSB* pRet = FGAS_GetUnicodeBitField(wUnicode); |
| 160 if (pRet->wBitField == 999) | 149 if (pRet->wBitField == 999) |
| 161 return nullptr; | 150 return nullptr; |
| 162 | 151 |
| 163 uint32_t dwHash = | 152 uint32_t dwHash = |
| 164 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField); | 153 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, pRet->wBitField); |
| 165 CFGAS_GEFont* pFont = nullptr; | 154 auto it = m_UnicodeFonts.find(dwHash); |
| 166 if (m_UnicodeFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) | 155 if (it != m_UnicodeFonts.end()) { |
| 167 return pFont ? LoadFont(pFont, dwFontStyles, pRet->wCodePage) : nullptr; | 156 return it->second ? LoadFont(it->second, dwFontStyles, pRet->wCodePage) |
| 168 | 157 : nullptr; |
| 169 FX_FONTDESCRIPTOR const* pFD = | 158 } |
| 159 const FX_FONTDESCRIPTOR* pFD = |
| 170 FindFont(pszFontFamily, dwFontStyles, false, pRet->wCodePage, | 160 FindFont(pszFontFamily, dwFontStyles, false, pRet->wCodePage, |
| 171 pRet->wBitField, wUnicode); | 161 pRet->wBitField, wUnicode); |
| 172 if (!pFD && pszFontFamily) { | 162 if (!pFD && pszFontFamily) { |
| 173 pFD = FindFont(nullptr, dwFontStyles, false, pRet->wCodePage, | 163 pFD = FindFont(nullptr, dwFontStyles, false, pRet->wCodePage, |
| 174 pRet->wBitField, wUnicode); | 164 pRet->wBitField, wUnicode); |
| 175 } | 165 } |
| 176 if (!pFD) | 166 if (!pFD) |
| 177 return nullptr; | 167 return nullptr; |
| 178 | 168 |
| 179 uint16_t wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); | 169 uint16_t wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); |
| 180 const FX_WCHAR* pFontFace = pFD->wsFontFace; | 170 const FX_WCHAR* pFontFace = pFD->wsFontFace; |
| 181 pFont = CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, wCodePage, this); | 171 CFX_RetainPtr<CFGAS_GEFont> pFont = |
| 172 CFGAS_GEFont::LoadFont(pFontFace, dwFontStyles, wCodePage, this); |
| 182 if (!pFont) | 173 if (!pFont) |
| 183 return nullptr; | 174 return nullptr; |
| 184 | 175 |
| 185 m_Fonts.Add(pFont); | 176 m_Fonts.push_back(pFont); |
| 186 m_UnicodeFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 177 m_UnicodeFonts[dwHash] = pFont; |
| 187 dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); | 178 m_CPFonts[FGAS_GetFontHashCode(wCodePage, dwFontStyles)] = pFont; |
| 188 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 179 m_FamilyFonts[FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage)] = |
| 189 dwHash = FGAS_GetFontFamilyHash(pFontFace, dwFontStyles, wCodePage); | 180 pFont; |
| 190 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | |
| 191 return LoadFont(pFont, dwFontStyles, wCodePage); | 181 return LoadFont(pFont, dwFontStyles, wCodePage); |
| 192 } | 182 } |
| 193 | 183 |
| 194 CFGAS_GEFont* CFGAS_FontMgr::LoadFont(const FX_WCHAR* pszFontFamily, | 184 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( |
| 195 uint32_t dwFontStyles, | 185 const FX_WCHAR* pszFontFamily, |
| 196 uint16_t wCodePage) { | 186 uint32_t dwFontStyles, |
| 187 uint16_t wCodePage) { |
| 188 CFX_RetainPtr<CFGAS_GEFont> pFont; |
| 197 uint32_t dwHash = | 189 uint32_t dwHash = |
| 198 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage); | 190 FGAS_GetFontFamilyHash(pszFontFamily, dwFontStyles, wCodePage); |
| 199 CFGAS_GEFont* pFont = nullptr; | 191 auto it = m_FamilyFonts.find(dwHash); |
| 200 if (m_FamilyFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont)) | 192 if (it != m_FamilyFonts.end()) |
| 201 return pFont ? LoadFont(pFont, dwFontStyles, wCodePage) : nullptr; | 193 return it->second ? LoadFont(it->second, dwFontStyles, wCodePage) : nullptr; |
| 202 FX_FONTDESCRIPTOR const* pFD = | 194 |
| 195 const FX_FONTDESCRIPTOR* pFD = |
| 203 FindFont(pszFontFamily, dwFontStyles, true, wCodePage); | 196 FindFont(pszFontFamily, dwFontStyles, true, wCodePage); |
| 204 if (!pFD) | 197 if (!pFD) |
| 205 pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage); | 198 pFD = FindFont(pszFontFamily, dwFontStyles, false, wCodePage); |
| 206 if (!pFD) | 199 if (!pFD) |
| 207 return nullptr; | 200 return nullptr; |
| 208 | 201 |
| 209 if (wCodePage == 0xFFFF) | 202 if (wCodePage == 0xFFFF) |
| 210 wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); | 203 wCodePage = FX_GetCodePageFromCharset(pFD->uCharSet); |
| 204 |
| 211 pFont = | 205 pFont = |
| 212 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); | 206 CFGAS_GEFont::LoadFont(pFD->wsFontFace, dwFontStyles, wCodePage, this); |
| 213 if (!pFont) | 207 if (!pFont) |
| 214 return nullptr; | 208 return nullptr; |
| 215 | 209 |
| 216 m_Fonts.Add(pFont); | 210 m_Fonts.push_back(pFont); |
| 217 m_FamilyFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 211 m_FamilyFonts[dwHash] = pFont; |
| 218 dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); | 212 dwHash = FGAS_GetFontHashCode(wCodePage, dwFontStyles); |
| 219 m_CPFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 213 m_CPFonts[dwHash] = pFont; |
| 220 return LoadFont(pFont, dwFontStyles, wCodePage); | 214 return LoadFont(pFont, dwFontStyles, wCodePage); |
| 221 } | 215 } |
| 222 | 216 |
| 223 CFGAS_GEFont* CFGAS_FontMgr::LoadFont(CFGAS_GEFont* pSrcFont, | 217 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( |
| 224 uint32_t dwFontStyles, | 218 const CFX_RetainPtr<CFGAS_GEFont>& pSrcFont, |
| 225 uint16_t wCodePage) { | 219 uint32_t dwFontStyles, |
| 226 ASSERT(pSrcFont); | 220 uint16_t wCodePage) { |
| 227 if (pSrcFont->GetFontStyles() == dwFontStyles) | 221 if (pSrcFont->GetFontStyles() == dwFontStyles) |
| 228 return pSrcFont->Retain(); | 222 return pSrcFont; |
| 229 void* buffer[3] = {pSrcFont, (void*)(uintptr_t)dwFontStyles, | 223 |
| 224 void* buffer[3] = {pSrcFont.Get(), (void*)(uintptr_t)dwFontStyles, |
| 230 (void*)(uintptr_t)wCodePage}; | 225 (void*)(uintptr_t)wCodePage}; |
| 231 uint32_t dwHash = FX_HashCode_GetA( | 226 uint32_t dwHash = FX_HashCode_GetA( |
| 232 CFX_ByteStringC((uint8_t*)buffer, sizeof(buffer)), false); | 227 CFX_ByteStringC((uint8_t*)buffer, sizeof(buffer)), false); |
| 233 CFGAS_GEFont* pFont = nullptr; | 228 auto it = m_DeriveFonts.find(dwHash); |
| 234 if (m_DeriveFonts.GetCount() > 0) { | 229 if (it != m_DeriveFonts.end() && it->second) |
| 235 m_DeriveFonts.Lookup((void*)(uintptr_t)dwHash, (void*&)pFont); | 230 return it->second; |
| 236 if (pFont) | 231 |
| 237 return pFont->Retain(); | 232 CFX_RetainPtr<CFGAS_GEFont> pFont = pSrcFont->Derive(dwFontStyles, wCodePage); |
| 238 } | |
| 239 pFont = pSrcFont->Derive(dwFontStyles, wCodePage); | |
| 240 if (!pFont) | 233 if (!pFont) |
| 241 return nullptr; | 234 return nullptr; |
| 242 | 235 |
| 243 m_DeriveFonts.SetAt((void*)(uintptr_t)dwHash, (void*)pFont); | 236 m_DeriveFonts[dwHash] = pFont; |
| 244 int32_t index = m_Fonts.Find(pFont); | 237 auto iter = std::find(m_Fonts.begin(), m_Fonts.end(), pFont); |
| 245 if (index < 0) { | 238 if (iter == m_Fonts.end()) |
| 246 m_Fonts.Add(pFont); | 239 m_Fonts.push_back(pFont); |
| 247 pFont->Retain(); | |
| 248 } | |
| 249 return pFont; | 240 return pFont; |
| 250 } | 241 } |
| 251 | 242 |
| 252 void CFGAS_FontMgr::RemoveFont(CFX_MapPtrToPtr& fontMap, CFGAS_GEFont* pFont) { | 243 void CFGAS_FontMgr::RemoveFont( |
| 253 FX_POSITION pos = fontMap.GetStartPosition(); | 244 std::map<uint32_t, CFX_RetainPtr<CFGAS_GEFont>>* pFontMap, |
| 254 void* pKey; | 245 const CFX_RetainPtr<CFGAS_GEFont>& pFont) { |
| 255 void* pFind; | 246 auto iter = pFontMap->begin(); |
| 256 while (pos) { | 247 while (iter != pFontMap->end()) { |
| 257 pFind = nullptr; | 248 auto old_iter = iter++; |
| 258 fontMap.GetNextAssoc(pos, pKey, pFind); | 249 if (old_iter->second == pFont) |
| 259 if (pFind != (void*)pFont) | 250 pFontMap->erase(old_iter); |
| 260 continue; | |
| 261 fontMap.RemoveKey(pKey); | |
| 262 break; | |
| 263 } | 251 } |
| 264 } | 252 } |
| 265 | 253 |
| 266 void CFGAS_FontMgr::RemoveFont(CFGAS_GEFont* pFont) { | 254 void CFGAS_FontMgr::RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pFont) { |
| 267 RemoveFont(m_CPFonts, pFont); | 255 RemoveFont(&m_CPFonts, pFont); |
| 268 RemoveFont(m_FamilyFonts, pFont); | 256 RemoveFont(&m_FamilyFonts, pFont); |
| 269 RemoveFont(m_UnicodeFonts, pFont); | 257 RemoveFont(&m_UnicodeFonts, pFont); |
| 270 RemoveFont(m_BufferFonts, pFont); | 258 RemoveFont(&m_BufferFonts, pFont); |
| 271 RemoveFont(m_StreamFonts, pFont); | 259 RemoveFont(&m_StreamFonts, pFont); |
| 272 RemoveFont(m_DeriveFonts, pFont); | 260 RemoveFont(&m_DeriveFonts, pFont); |
| 273 int32_t iFind = m_Fonts.Find(pFont); | 261 auto it = std::find(m_Fonts.begin(), m_Fonts.end(), pFont); |
| 274 if (iFind > -1) | 262 if (it != m_Fonts.end()) |
| 275 m_Fonts.RemoveAt(iFind, 1); | 263 m_Fonts.erase(it); |
| 276 } | 264 } |
| 277 | 265 |
| 278 FX_FONTDESCRIPTOR const* CFGAS_FontMgr::FindFont(const FX_WCHAR* pszFontFamily, | 266 FX_FONTDESCRIPTOR const* CFGAS_FontMgr::FindFont(const FX_WCHAR* pszFontFamily, |
| 279 uint32_t dwFontStyles, | 267 uint32_t dwFontStyles, |
| 280 uint32_t dwMatchFlags, | 268 uint32_t dwMatchFlags, |
| 281 uint16_t wCodePage, | 269 uint16_t wCodePage, |
| 282 uint32_t dwUSB, | 270 uint32_t dwUSB, |
| 283 FX_WCHAR wUnicode) { | 271 FX_WCHAR wUnicode) { |
| 284 FX_FONTMATCHPARAMS params; | 272 FX_FONTMATCHPARAMS params; |
| 285 FXSYS_memset(¶ms, 0, sizeof(params)); | 273 FXSYS_memset(¶ms, 0, sizeof(params)); |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 CFGAS_FontMgr::~CFGAS_FontMgr() { | 575 CFGAS_FontMgr::~CFGAS_FontMgr() { |
| 588 for (int32_t i = 0; i < m_InstalledFonts.GetSize(); i++) | 576 for (int32_t i = 0; i < m_InstalledFonts.GetSize(); i++) |
| 589 delete m_InstalledFonts[i]; | 577 delete m_InstalledFonts[i]; |
| 590 FX_POSITION pos = m_Hash2CandidateList.GetStartPosition(); | 578 FX_POSITION pos = m_Hash2CandidateList.GetStartPosition(); |
| 591 while (pos) { | 579 while (pos) { |
| 592 uint32_t dwHash; | 580 uint32_t dwHash; |
| 593 CFX_FontDescriptorInfos* pDescs; | 581 CFX_FontDescriptorInfos* pDescs; |
| 594 m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs); | 582 m_Hash2CandidateList.GetNextAssoc(pos, dwHash, pDescs); |
| 595 delete pDescs; | 583 delete pDescs; |
| 596 } | 584 } |
| 597 pos = m_Hash2Fonts.GetStartPosition(); | 585 m_Hash2Fonts.clear(); |
| 598 while (pos) { | |
| 599 uint32_t dwHash; | |
| 600 CFX_ArrayTemplate<CFGAS_GEFont*>* pFonts; | |
| 601 m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts); | |
| 602 for (int32_t i = 0; i < pFonts->GetSize(); i++) | |
| 603 delete pFonts->GetAt(i); | |
| 604 delete pFonts; | |
| 605 } | |
| 606 m_Hash2Fonts.RemoveAll(); | |
| 607 } | 586 } |
| 608 | 587 |
| 609 bool CFGAS_FontMgr::EnumFontsFromFontMapper() { | 588 bool CFGAS_FontMgr::EnumFontsFromFontMapper() { |
| 610 CFX_FontMapper* pFontMapper = | 589 CFX_FontMapper* pFontMapper = |
| 611 CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper(); | 590 CFX_GEModule::Get()->GetFontMgr()->GetBuiltinMapper(); |
| 612 if (!pFontMapper) | 591 if (!pFontMapper) |
| 613 return false; | 592 return false; |
| 614 | 593 |
| 615 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo(); | 594 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo(); |
| 616 if (!pSystemFontInfo) | 595 if (!pSystemFontInfo) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 637 CFX_RetainPtr<IFX_FileAccess> pFontSource = m_pFontSource->GetNext(pos); | 616 CFX_RetainPtr<IFX_FileAccess> pFontSource = m_pFontSource->GetNext(pos); |
| 638 CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = | 617 CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = |
| 639 pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly); | 618 pFontSource->CreateFileStream(FX_FILEMODE_ReadOnly); |
| 640 if (pFontStream) | 619 if (pFontStream) |
| 641 RegisterFaces(pFontStream, nullptr); | 620 RegisterFaces(pFontStream, nullptr); |
| 642 } | 621 } |
| 643 return m_InstalledFonts.GetSize() != 0; | 622 return m_InstalledFonts.GetSize() != 0; |
| 644 } | 623 } |
| 645 | 624 |
| 646 bool CFGAS_FontMgr::EnumFonts() { | 625 bool CFGAS_FontMgr::EnumFonts() { |
| 647 if (EnumFontsFromFontMapper()) | 626 return EnumFontsFromFontMapper() || EnumFontsFromFiles(); |
| 648 return true; | |
| 649 return EnumFontsFromFiles(); | |
| 650 } | 627 } |
| 651 | 628 |
| 652 CFGAS_GEFont* CFGAS_FontMgr::GetFontByCodePage(uint16_t wCodePage, | 629 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( |
| 653 uint32_t dwFontStyles, | 630 const FX_WCHAR* pszFontFamily, |
| 654 const FX_WCHAR* pszFontFamily) { | 631 uint32_t dwFontStyles, |
| 632 uint16_t wCodePage) { |
| 633 return GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily); |
| 634 } |
| 635 |
| 636 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByCodePage( |
| 637 uint16_t wCodePage, |
| 638 uint32_t dwFontStyles, |
| 639 const FX_WCHAR* pszFontFamily) { |
| 655 CFX_ByteString bsHash; | 640 CFX_ByteString bsHash; |
| 656 bsHash.Format("%d, %d", wCodePage, dwFontStyles); | 641 bsHash.Format("%d, %d", wCodePage, dwFontStyles); |
| 657 bsHash += CFX_WideString(pszFontFamily).UTF8Encode(); | 642 bsHash += CFX_WideString(pszFontFamily).UTF8Encode(); |
| 658 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); | 643 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); |
| 659 CFX_ArrayTemplate<CFGAS_GEFont*>* pFonts = nullptr; | 644 std::vector<CFX_RetainPtr<CFGAS_GEFont>>* pFontArray = &m_Hash2Fonts[dwHash]; |
| 660 if (m_Hash2Fonts.Lookup(dwHash, pFonts)) { | 645 if (!pFontArray->empty()) |
| 661 if (!pFonts) | 646 return (*pFontArray)[0]; |
| 662 return nullptr; | |
| 663 | 647 |
| 664 if (pFonts->GetSize() != 0) | |
| 665 return pFonts->GetAt(0)->Retain(); | |
| 666 } | |
| 667 | |
| 668 if (!pFonts) | |
| 669 pFonts = new CFX_ArrayTemplate<CFGAS_GEFont*>; | |
| 670 | |
| 671 m_Hash2Fonts.SetAt(dwHash, pFonts); | |
| 672 CFX_FontDescriptorInfos* sortedFonts = nullptr; | 648 CFX_FontDescriptorInfos* sortedFonts = nullptr; |
| 673 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) { | 649 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) { |
| 674 sortedFonts = new CFX_FontDescriptorInfos; | 650 sortedFonts = new CFX_FontDescriptorInfos; |
| 675 MatchFonts(*sortedFonts, wCodePage, dwFontStyles, | 651 MatchFonts(*sortedFonts, wCodePage, dwFontStyles, |
| 676 CFX_WideString(pszFontFamily), 0); | 652 CFX_WideString(pszFontFamily), 0); |
| 677 m_Hash2CandidateList.SetAt(dwHash, sortedFonts); | 653 m_Hash2CandidateList.SetAt(dwHash, sortedFonts); |
| 678 } | 654 } |
| 679 if (sortedFonts->GetSize() == 0) | 655 if (sortedFonts->GetSize() == 0) |
| 680 return nullptr; | 656 return nullptr; |
| 681 | 657 |
| 682 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(0).pFont; | 658 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(0).pFont; |
| 683 CFGAS_GEFont* pFont = | 659 CFX_RetainPtr<CFGAS_GEFont> pFont = |
| 684 LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); | 660 LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); |
| 685 if (pFont) | 661 if (!pFont) |
| 686 pFont->SetLogicalFontStyle(dwFontStyles); | 662 return nullptr; |
| 687 | 663 |
| 688 pFonts->Add(pFont); | 664 pFont->SetLogicalFontStyle(dwFontStyles); |
| 665 pFontArray->push_back(pFont); |
| 689 return pFont; | 666 return pFont; |
| 690 } | 667 } |
| 691 | 668 |
| 692 CFGAS_GEFont* CFGAS_FontMgr::GetFontByUnicode(FX_WCHAR wUnicode, | 669 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::GetFontByUnicode( |
| 693 uint32_t dwFontStyles, | 670 FX_WCHAR wUnicode, |
| 694 const FX_WCHAR* pszFontFamily) { | 671 uint32_t dwFontStyles, |
| 695 CFGAS_GEFont* pFont = nullptr; | 672 const FX_WCHAR* pszFontFamily) { |
| 696 if (m_FailedUnicodes2Nullptr.Lookup(wUnicode, pFont)) | 673 if (pdfium::ContainsKey(m_FailedUnicodesSet, wUnicode)) |
| 697 return nullptr; | 674 return nullptr; |
| 675 |
| 698 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode); | 676 const FGAS_FONTUSB* x = FGAS_GetUnicodeBitField(wUnicode); |
| 699 uint16_t wCodePage = x ? x->wCodePage : 0xFFFF; | 677 uint16_t wCodePage = x ? x->wCodePage : 0xFFFF; |
| 700 uint16_t wBitField = x ? x->wBitField : 0x03E7; | 678 uint16_t wBitField = x ? x->wBitField : 0x03E7; |
| 701 CFX_ByteString bsHash; | 679 CFX_ByteString bsHash; |
| 702 if (wCodePage == 0xFFFF) | 680 if (wCodePage == 0xFFFF) |
| 703 bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles); | 681 bsHash.Format("%d, %d, %d", wCodePage, wBitField, dwFontStyles); |
| 704 else | 682 else |
| 705 bsHash.Format("%d, %d", wCodePage, dwFontStyles); | 683 bsHash.Format("%d, %d", wCodePage, dwFontStyles); |
| 706 bsHash += CFX_WideString(pszFontFamily).UTF8Encode(); | 684 bsHash += CFX_WideString(pszFontFamily).UTF8Encode(); |
| 707 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); | 685 uint32_t dwHash = FX_HashCode_GetA(bsHash.AsStringC(), false); |
| 708 CFX_ArrayTemplate<CFGAS_GEFont*>* pFonts = nullptr; | 686 std::vector<CFX_RetainPtr<CFGAS_GEFont>>* pFonts = &m_Hash2Fonts[dwHash]; |
| 709 if (m_Hash2Fonts.Lookup(dwHash, pFonts)) { | 687 for (size_t i = 0; i < pFonts->size(); ++i) { |
| 710 if (!pFonts) | 688 if (VerifyUnicode((*pFonts)[i], wUnicode)) |
| 711 return nullptr; | 689 return (*pFonts)[i]; |
| 712 | |
| 713 for (int32_t i = 0; i < pFonts->GetSize(); ++i) { | |
| 714 if (VerifyUnicode(pFonts->GetAt(i), wUnicode)) | |
| 715 return pFonts->GetAt(i)->Retain(); | |
| 716 } | |
| 717 } | 690 } |
| 718 if (!pFonts) | |
| 719 pFonts = new CFX_ArrayTemplate<CFGAS_GEFont*>; | |
| 720 m_Hash2Fonts.SetAt(dwHash, pFonts); | |
| 721 CFX_FontDescriptorInfos* sortedFonts = nullptr; | 691 CFX_FontDescriptorInfos* sortedFonts = nullptr; |
| 722 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) { | 692 if (!m_Hash2CandidateList.Lookup(dwHash, sortedFonts)) { |
| 723 sortedFonts = new CFX_FontDescriptorInfos; | 693 sortedFonts = new CFX_FontDescriptorInfos; |
| 724 MatchFonts(*sortedFonts, wCodePage, dwFontStyles, | 694 MatchFonts(*sortedFonts, wCodePage, dwFontStyles, |
| 725 CFX_WideString(pszFontFamily), wUnicode); | 695 CFX_WideString(pszFontFamily), wUnicode); |
| 726 m_Hash2CandidateList.SetAt(dwHash, sortedFonts); | 696 m_Hash2CandidateList.SetAt(dwHash, sortedFonts); |
| 727 } | 697 } |
| 728 for (int32_t i = 0; i < sortedFonts->GetSize(); ++i) { | 698 for (int32_t i = 0; i < sortedFonts->GetSize(); ++i) { |
| 729 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(i).pFont; | 699 CFX_FontDescriptor* pDesc = sortedFonts->GetAt(i).pFont; |
| 730 if (!VerifyUnicode(pDesc, wUnicode)) | 700 if (!VerifyUnicode(pDesc, wUnicode)) |
| 731 continue; | 701 continue; |
| 732 pFont = LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); | 702 CFX_RetainPtr<CFGAS_GEFont> pFont = |
| 703 LoadFont(pDesc->m_wsFaceName, pDesc->m_nFaceIndex, nullptr); |
| 733 if (!pFont) | 704 if (!pFont) |
| 734 continue; | 705 continue; |
| 735 pFont->SetLogicalFontStyle(dwFontStyles); | 706 pFont->SetLogicalFontStyle(dwFontStyles); |
| 736 pFonts->Add(pFont); | 707 pFonts->push_back(pFont); |
| 737 return pFont; | 708 return pFont; |
| 738 } | 709 } |
| 739 if (!pszFontFamily) | 710 if (!pszFontFamily) |
| 740 m_FailedUnicodes2Nullptr.SetAt(wUnicode, nullptr); | 711 m_FailedUnicodesSet.insert(wUnicode); |
| 741 return nullptr; | 712 return nullptr; |
| 742 } | 713 } |
| 743 | 714 |
| 744 bool CFGAS_FontMgr::VerifyUnicode(CFX_FontDescriptor* pDesc, | 715 bool CFGAS_FontMgr::VerifyUnicode(CFX_FontDescriptor* pDesc, |
| 745 FX_WCHAR wcUnicode) { | 716 FX_WCHAR wcUnicode) { |
| 746 CFX_RetainPtr<IFX_SeekableReadStream> pFileRead = | 717 CFX_RetainPtr<IFX_SeekableReadStream> pFileRead = |
| 747 CreateFontStream(pDesc->m_wsFaceName.UTF8Encode()); | 718 CreateFontStream(pDesc->m_wsFaceName.UTF8Encode()); |
| 748 if (!pFileRead) | 719 if (!pFileRead) |
| 749 return false; | 720 return false; |
| 750 | 721 |
| 751 FXFT_Face pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex); | 722 FXFT_Face pFace = LoadFace(pFileRead, pDesc->m_nFaceIndex); |
| 752 FT_Error retCharmap = FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE); | 723 FT_Error retCharmap = FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE); |
| 753 FT_Error retIndex = FXFT_Get_Char_Index(pFace, wcUnicode); | 724 FT_Error retIndex = FXFT_Get_Char_Index(pFace, wcUnicode); |
| 754 if (!pFace) | 725 if (!pFace) |
| 755 return false; | 726 return false; |
| 756 | 727 |
| 757 if (FXFT_Get_Face_External_Stream(pFace)) | 728 if (FXFT_Get_Face_External_Stream(pFace)) |
| 758 FXFT_Clear_Face_External_Stream(pFace); | 729 FXFT_Clear_Face_External_Stream(pFace); |
| 759 | 730 |
| 760 FXFT_Done_Face(pFace); | 731 FXFT_Done_Face(pFace); |
| 761 return !retCharmap && retIndex; | 732 return !retCharmap && retIndex; |
| 762 } | 733 } |
| 763 | 734 |
| 764 bool CFGAS_FontMgr::VerifyUnicode(CFGAS_GEFont* pFont, FX_WCHAR wcUnicode) { | 735 bool CFGAS_FontMgr::VerifyUnicode(const CFX_RetainPtr<CFGAS_GEFont>& pFont, |
| 736 FX_WCHAR wcUnicode) { |
| 765 if (!pFont) | 737 if (!pFont) |
| 766 return false; | 738 return false; |
| 767 | 739 |
| 768 FXFT_Face pFace = pFont->GetDevFont()->GetFace(); | 740 FXFT_Face pFace = pFont->GetDevFont()->GetFace(); |
| 769 FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace); | 741 FXFT_CharMap charmap = FXFT_Get_Face_Charmap(pFace); |
| 770 if (FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE) != 0) | 742 if (FXFT_Select_Charmap(pFace, FXFT_ENCODING_UNICODE) != 0) |
| 771 return false; | 743 return false; |
| 772 | 744 |
| 773 if (FXFT_Get_Char_Index(pFace, wcUnicode) == 0) { | 745 if (FXFT_Get_Char_Index(pFace, wcUnicode) == 0) { |
| 774 FXFT_Set_Charmap(pFace, charmap); | 746 FXFT_Set_Charmap(pFace, charmap); |
| 775 return false; | 747 return false; |
| 776 } | 748 } |
| 777 return true; | 749 return true; |
| 778 } | 750 } |
| 779 | 751 |
| 780 CFGAS_GEFont* CFGAS_FontMgr::LoadFont(const CFX_WideString& wsFaceName, | 752 CFX_RetainPtr<CFGAS_GEFont> CFGAS_FontMgr::LoadFont( |
| 781 int32_t iFaceIndex, | 753 const CFX_WideString& wsFaceName, |
| 782 int32_t* pFaceCount) { | 754 int32_t iFaceIndex, |
| 755 int32_t* pFaceCount) { |
| 783 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); | 756 CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); |
| 784 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper(); | 757 CFX_FontMapper* pFontMapper = pFontMgr->GetBuiltinMapper(); |
| 785 if (!pFontMapper) | 758 if (!pFontMapper) |
| 786 return nullptr; | 759 return nullptr; |
| 787 | 760 |
| 788 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo(); | 761 IFX_SystemFontInfo* pSystemFontInfo = pFontMapper->GetSystemFontInfo(); |
| 789 if (!pSystemFontInfo) | 762 if (!pSystemFontInfo) |
| 790 return nullptr; | 763 return nullptr; |
| 791 | 764 |
| 792 CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = | 765 CFX_RetainPtr<IFX_SeekableReadStream> pFontStream = |
| 793 CreateFontStream(wsFaceName.UTF8Encode()); | 766 CreateFontStream(wsFaceName.UTF8Encode()); |
| 794 if (!pFontStream) | 767 if (!pFontStream) |
| 795 return nullptr; | 768 return nullptr; |
| 796 | 769 |
| 797 auto pInternalFont = pdfium::MakeUnique<CFX_Font>(); | 770 auto pInternalFont = pdfium::MakeUnique<CFX_Font>(); |
| 798 if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) | 771 if (!pInternalFont->LoadFile(pFontStream, iFaceIndex)) |
| 799 return nullptr; | 772 return nullptr; |
| 800 | 773 |
| 801 CFGAS_GEFont* pFont = CFGAS_GEFont::LoadFont(std::move(pInternalFont), this); | 774 CFX_RetainPtr<CFGAS_GEFont> pFont = |
| 775 CFGAS_GEFont::LoadFont(std::move(pInternalFont), this); |
| 802 if (!pFont) | 776 if (!pFont) |
| 803 return nullptr; | 777 return nullptr; |
| 804 | 778 |
| 805 m_IFXFont2FileRead[pFont] = pFontStream; | 779 m_IFXFont2FileRead[pFont] = pFontStream; |
| 806 if (pFaceCount) | 780 if (pFaceCount) |
| 807 *pFaceCount = pFont->GetDevFont()->GetFace()->num_faces; | 781 *pFaceCount = pFont->GetDevFont()->GetFace()->num_faces; |
| 808 | |
| 809 return pFont; | 782 return pFont; |
| 810 } | 783 } |
| 811 | 784 |
| 812 extern "C" { | 785 extern "C" { |
| 813 | 786 |
| 814 unsigned long _ftStreamRead(FXFT_Stream stream, | 787 unsigned long _ftStreamRead(FXFT_Stream stream, |
| 815 unsigned long offset, | 788 unsigned long offset, |
| 816 unsigned char* buffer, | 789 unsigned char* buffer, |
| 817 unsigned long count) { | 790 unsigned long count) { |
| 818 if (count == 0) | 791 if (count == 0) |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 if (wBit != static_cast<uint16_t>(999)) { | 976 if (wBit != static_cast<uint16_t>(999)) { |
| 1004 ASSERT(wBit < 128); | 977 ASSERT(wBit < 128); |
| 1005 if ((pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32))) == 0) | 978 if ((pInstalled->m_dwUsb[wBit / 32] & (1 << (wBit % 32))) == 0) |
| 1006 nPenalty += 0xFFFF; | 979 nPenalty += 0xFFFF; |
| 1007 else | 980 else |
| 1008 nPenalty -= 60000; | 981 nPenalty -= 60000; |
| 1009 } | 982 } |
| 1010 return nPenalty; | 983 return nPenalty; |
| 1011 } | 984 } |
| 1012 | 985 |
| 1013 void CFGAS_FontMgr::RemoveFont(CFGAS_GEFont* pEFont) { | 986 void CFGAS_FontMgr::RemoveFont(const CFX_RetainPtr<CFGAS_GEFont>& pEFont) { |
| 1014 if (!pEFont) | 987 if (!pEFont) |
| 1015 return; | 988 return; |
| 1016 | 989 |
| 1017 m_IFXFont2FileRead.erase(pEFont); | 990 m_IFXFont2FileRead.erase(pEFont); |
| 1018 | 991 |
| 1019 FX_POSITION pos; | 992 auto iter = m_Hash2Fonts.begin(); |
| 1020 pos = m_Hash2Fonts.GetStartPosition(); | 993 while (iter != m_Hash2Fonts.end()) { |
| 1021 while (pos) { | 994 auto old_iter = iter++; |
| 1022 uint32_t dwHash; | 995 bool all_empty = true; |
| 1023 CFX_ArrayTemplate<CFGAS_GEFont*>* pFonts; | 996 for (size_t i = 0; i < old_iter->second.size(); i++) { |
| 1024 m_Hash2Fonts.GetNextAssoc(pos, dwHash, pFonts); | 997 if (old_iter->second[i] == pEFont) |
| 1025 if (pFonts) { | 998 old_iter->second[i].Reset(); |
| 1026 for (int32_t i = 0; i < pFonts->GetSize(); i++) { | 999 else if (old_iter->second[i]) |
| 1027 if (pFonts->GetAt(i) == pEFont) | 1000 all_empty = false; |
| 1028 pFonts->SetAt(i, nullptr); | |
| 1029 } | |
| 1030 } else { | |
| 1031 m_Hash2Fonts.RemoveKey(dwHash); | |
| 1032 } | 1001 } |
| 1002 if (all_empty) |
| 1003 m_Hash2Fonts.erase(old_iter); |
| 1033 } | 1004 } |
| 1034 } | 1005 } |
| 1035 | 1006 |
| 1036 void CFGAS_FontMgr::RegisterFace(FXFT_Face pFace, | 1007 void CFGAS_FontMgr::RegisterFace(FXFT_Face pFace, |
| 1037 const CFX_WideString* pFaceName) { | 1008 const CFX_WideString* pFaceName) { |
| 1038 if ((pFace->face_flags & FT_FACE_FLAG_SCALABLE) == 0) | 1009 if ((pFace->face_flags & FT_FACE_FLAG_SCALABLE) == 0) |
| 1039 return; | 1010 return; |
| 1040 | 1011 |
| 1041 std::unique_ptr<CFX_FontDescriptor> pFont(new CFX_FontDescriptor); | 1012 std::unique_ptr<CFX_FontDescriptor> pFont(new CFX_FontDescriptor); |
| 1042 pFont->m_dwFontStyles |= FXFT_Is_Face_Bold(pFace) ? FX_FONTSTYLE_Bold : 0; | 1013 pFont->m_dwFontStyles |= FXFT_Is_Face_Bold(pFace) ? FX_FONTSTYLE_Bold : 0; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 } | 1150 } |
| 1180 | 1151 |
| 1181 int32_t CFGAS_FontMgr::IsPartName(const CFX_WideString& Name1, | 1152 int32_t CFGAS_FontMgr::IsPartName(const CFX_WideString& Name1, |
| 1182 const CFX_WideString& Name2) { | 1153 const CFX_WideString& Name2) { |
| 1183 if (Name1.Find(Name2.c_str()) != -1) | 1154 if (Name1.Find(Name2.c_str()) != -1) |
| 1184 return 1; | 1155 return 1; |
| 1185 return 0; | 1156 return 0; |
| 1186 } | 1157 } |
| 1187 | 1158 |
| 1188 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 1159 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| OLD | NEW |