diff options
Diffstat (limited to 'core/fpdfapi')
-rw-r--r-- | core/fpdfapi/fpdf_font/cpdf_font.cpp | 24 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_font/include/cpdf_font.h | 3 | ||||
-rw-r--r-- | core/fpdfapi/fpdf_render/fpdf_render_text.cpp | 95 |
3 files changed, 111 insertions, 11 deletions
diff --git a/core/fpdfapi/fpdf_font/cpdf_font.cpp b/core/fpdfapi/fpdf_font/cpdf_font.cpp index 8101bd49a6..4747093ac4 100644 --- a/core/fpdfapi/fpdf_font/cpdf_font.cpp +++ b/core/fpdfapi/fpdf_font/cpdf_font.cpp @@ -22,7 +22,9 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_name.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream_acc.h" #include "core/fpdfapi/include/cpdf_modulemgr.h" +#include "core/fxcrt/include/fx_memory.h" #include "core/fxge/include/fx_freetype.h" +#include "third_party/base/stl_util.h" namespace { @@ -451,3 +453,25 @@ const FX_CHAR* CPDF_Font::GetAdobeCharName( name = PDF_CharNameFromPredefinedCharSet(iBaseEncoding, charcode); return name && name[0] ? name : nullptr; } + +uint32_t CPDF_Font::FallbackFontFromCharcode(uint32_t charcode) { + if (m_FontFallbacks.empty()) { + m_FontFallbacks.push_back(WrapUnique(new CFX_Font())); + m_FontFallbacks[0]->LoadSubst("Arial", IsTrueTypeFont(), m_Flags, + m_StemV * 5, m_ItalicAngle, 0, + IsVertWriting()); + } + return 0; +} + +int CPDF_Font::FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode) { + if (fallbackFont < 0 || + fallbackFont >= pdfium::CollectionSize<int>(m_FontFallbacks)) { + return -1; + } + int glyph = + FXFT_Get_Char_Index(m_FontFallbacks[fallbackFont]->GetFace(), charcode); + if (glyph == 0 || glyph == 0xffff) + return -1; + return glyph; +} diff --git a/core/fpdfapi/fpdf_font/include/cpdf_font.h b/core/fpdfapi/fpdf_font/include/cpdf_font.h index a76a6a2573..a47d8655c2 100644 --- a/core/fpdfapi/fpdf_font/include/cpdf_font.h +++ b/core/fpdfapi/fpdf_font/include/cpdf_font.h @@ -88,12 +88,15 @@ class CPDF_Font { int GetItalicAngle() const { return m_ItalicAngle; } int GetStemV() const { return m_StemV; } int GetStringWidth(const FX_CHAR* pString, int size); + uint32_t FallbackFontFromCharcode(uint32_t charcode); + int FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode); virtual int GetCharWidthF(uint32_t charcode, int level = 0) = 0; virtual FX_RECT GetCharBBox(uint32_t charcode, int level = 0) = 0; CPDF_Document* m_pDocument; CFX_Font m_Font; + std::vector<std::unique_ptr<CFX_Font>> m_FontFallbacks; protected: CPDF_Font(); diff --git a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp index 641d0b4705..16d1235f4d 100644 --- a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp +++ b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp @@ -371,6 +371,7 @@ class CPDF_RefType3Cache { CPDF_Type3Font* const m_pType3Font; }; +// TODO(npm): Font fallback for type 3 fonts? (Completely separate code!!) FX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_Matrix* pObj2Device) { CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->AsType3Font(); @@ -572,6 +573,15 @@ void CPDF_CharPosList::Load(int nChars, charpos.m_bFontStyle = true; } charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert); + if (charpos.m_GlyphIndex != static_cast<uint32_t>(-1)) { + charpos.m_FallbackFontPosition = -1; + } else { + charpos.m_FallbackFontPosition = + pFont->FallbackFontFromCharcode(CharCode); + charpos.m_GlyphIndex = pFont->FallbackGlyphFromCharcode( + charpos.m_FallbackFontPosition, CharCode); + } +// TODO(npm): Figure out how this affects m_ExtGID #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); #endif @@ -629,10 +639,36 @@ FX_BOOL CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, : nullptr; CPDF_CharPosList CharPosList; CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); - return pDevice->DrawTextPath(CharPosList.m_nChars, CharPosList.m_pCharPos, - &pFont->m_Font, pCache, font_size, pText2User, - pUser2Device, pGraphState, fill_argb, - stroke_argb, pClippingPath, nFlag); + if (CharPosList.m_nChars == 0) + return TRUE; + bool bDraw = true; + int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition; + uint32_t startIndex = 0; + for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { + int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; + if (fontPosition == curFontPosition) + continue; + auto* font = fontPosition == -1 + ? &pFont->m_Font + : pFont->m_FontFallbacks[fontPosition].get(); + if (!pDevice->DrawTextPath( + i - startIndex, CharPosList.m_pCharPos + startIndex, font, pCache, + font_size, pText2User, pUser2Device, pGraphState, fill_argb, + stroke_argb, pClippingPath, nFlag)) { + bDraw = false; + } + fontPosition = curFontPosition; + startIndex = i; + } + auto* font = fontPosition == -1 ? &pFont->m_Font + : pFont->m_FontFallbacks[fontPosition].get(); + if (!pDevice->DrawTextPath(CharPosList.m_nChars - startIndex, + CharPosList.m_pCharPos + startIndex, font, pCache, + font_size, pText2User, pUser2Device, pGraphState, + fill_argb, stroke_argb, pClippingPath, nFlag)) { + bDraw = false; + } + return bDraw; } // static @@ -708,6 +744,8 @@ FX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, : nullptr; CPDF_CharPosList CharPosList; CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); + if (CharPosList.m_nChars == 0) + return TRUE; int FXGE_flags = 0; if (pOptions) { uint32_t dwFlags = pOptions->m_Flags; @@ -735,9 +773,33 @@ FX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, if (pFont->IsCIDFont()) { FXGE_flags |= FXFONT_CIDFONT; } - return pDevice->DrawNormalText(CharPosList.m_nChars, CharPosList.m_pCharPos, - &pFont->m_Font, pCache, font_size, - pText2Device, fill_argb, FXGE_flags); + bool bDraw = true; + int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition; + uint32_t startIndex = 0; + for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { + int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; + if (fontPosition == curFontPosition) + continue; + auto* font = fontPosition == -1 + ? &pFont->m_Font + : pFont->m_FontFallbacks[fontPosition].get(); + if (!pDevice->DrawNormalText( + i - startIndex, CharPosList.m_pCharPos + startIndex, font, pCache, + font_size, pText2Device, fill_argb, FXGE_flags)) { + bDraw = false; + } + fontPosition = curFontPosition; + startIndex = i; + } + auto* font = fontPosition == -1 ? &pFont->m_Font + : pFont->m_FontFallbacks[fontPosition].get(); + if (!pDevice->DrawNormalText(CharPosList.m_nChars - startIndex, + CharPosList.m_pCharPos + startIndex, font, + pCache, font_size, pText2Device, fill_argb, + FXGE_flags)) { + bDraw = false; + } + return bDraw; } void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, @@ -770,15 +832,26 @@ void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, } else { pCache = CFX_GEModule::Get()->GetFontCache(); } - CFX_FaceCache* pFaceCache = pCache->GetCachedFace(&pFont->m_Font); - CFX_AutoFontCache autoFontCache(pCache, &pFont->m_Font); CPDF_CharPosList CharPosList; CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size); + std::vector<CFX_FaceCache*> faceCaches; + std::vector<CFX_AutoFontCache> autoFontCaches; + faceCaches.push_back(pCache->GetCachedFace(&pFont->m_Font)); + autoFontCaches.push_back(CFX_AutoFontCache(pCache, &pFont->m_Font)); + for (const auto& font : pFont->m_FontFallbacks) { + faceCaches.push_back(pCache->GetCachedFace(font.get())); + autoFontCaches.push_back(CFX_AutoFontCache(pCache, font.get())); + } for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i]; - const CFX_PathData* pPath = pFaceCache->LoadGlyphPath( - &pFont->m_Font, charpos.m_GlyphIndex, charpos.m_FontCharWidth); + auto font = + charpos.m_FallbackFontPosition == -1 + ? &pFont->m_Font + : pFont->m_FontFallbacks[charpos.m_FallbackFontPosition].get(); + const CFX_PathData* pPath = + faceCaches[charpos.m_FallbackFontPosition + 1]->LoadGlyphPath( + font, charpos.m_GlyphIndex, charpos.m_FontCharWidth); if (!pPath) { continue; } |