Index: core/fpdfapi/fpdf_render/fpdf_render_text.cpp |
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp |
index 641d0b4705aa88a8f136b8dff133b1fe7f81b1c1..16d1235f4db2b4e435d8bf24c1fede4c73a3b2bd 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; |
} |