summaryrefslogtreecommitdiff
path: root/core/fpdfapi/fpdf_render
diff options
context:
space:
mode:
authornpm <npm@chromium.org>2016-08-24 11:23:49 -0700
committerCommit bot <commit-bot@chromium.org>2016-08-24 11:23:49 -0700
commitb107193e9780b4a50e85d54c1ffbd2303263e193 (patch)
treefb81a07ad10477d16af26667aa4e4629328b6084 /core/fpdfapi/fpdf_render
parentcedaa557316a3f5c436814e69d67f19795f471d7 (diff)
downloadpdfium-b107193e9780b4a50e85d54c1ffbd2303263e193.tar.xz
Allow CPDF_Font to use fallback fonts
Added a vector of pointers to CFX_Fonts in the class CPDF_Font, so that fallback fonts may be used. In CPDF_CharPosList::Load, the glyphs for each character are calculated. When m_Font does not support a character, a fallback font is selected and the character is rendered using that font. This meant adding an attribute to FXTEXT_CHARPOS so it knows which font renders it. Also, methods in fpdf_render_text.cpp now may need to call device drawing methods multiple times because these only support one font at a time. In CPDF_TextRenderer::DrawNormalText and in CPDF_TextRenderer::DrawTextPath, the device drawing method is called as few times as possible by grouping contiguous characters rendered by the same font. In CPDF_RenderStatus::DrawTextPathWithPattern, drawing was already done one character at a time, but precalculating CFX_FaceCache. Now, the face cache is precalculated for all of the fallback fonts. The list of fallback fonts does not include tha main font. Otherwise the list would be of raw pointers to avoid double free problems. For now, the font Arial is used as fallback. This should fix the issue of not seeing Latin characters displayed when bad fonts are used. However, this should be improved. Tested manually using the file in the bug, plus a font directory containing a font that supports Hangul but not Latin. This font is chosen as the substitute font, but Latin characters are now being rendered. Design proposal: go/pdfium_fallbackfonts BUG=pdfium:358 Review-Url: https://codereview.chromium.org/2276653002
Diffstat (limited to 'core/fpdfapi/fpdf_render')
-rw-r--r--core/fpdfapi/fpdf_render/fpdf_render_text.cpp95
1 files changed, 84 insertions, 11 deletions
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;
}