summaryrefslogtreecommitdiff
path: root/core/fpdfapi
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi')
-rw-r--r--core/fpdfapi/fpdf_font/cpdf_font.cpp24
-rw-r--r--core/fpdfapi/fpdf_font/include/cpdf_font.h3
-rw-r--r--core/fpdfapi/fpdf_render/fpdf_render_text.cpp95
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;
}