void CPDF_Font::CheckFontMetrics() { if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 && m_FontBBox.right == 0) { FXFT_Face face = m_Font.GetFace(); if (face) { m_FontBBox.left = TT2PDF(FXFT_Get_Face_xMin(face), face); m_FontBBox.bottom = TT2PDF(FXFT_Get_Face_yMin(face), face); m_FontBBox.right = TT2PDF(FXFT_Get_Face_xMax(face), face); m_FontBBox.top = TT2PDF(FXFT_Get_Face_yMax(face), face); m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face); m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face); } else { bool bFirst = true; for (int i = 0; i < 256; i++) { FX_RECT rect = GetCharBBox(i); if (rect.left == rect.right) { continue; } if (bFirst) { m_FontBBox = rect; bFirst = false; } else { if (m_FontBBox.top < rect.top) { m_FontBBox.top = rect.top; } if (m_FontBBox.right < rect.right) { m_FontBBox.right = rect.right; } if (m_FontBBox.left > rect.left) { m_FontBBox.left = rect.left; } if (m_FontBBox.bottom > rect.bottom) { m_FontBBox.bottom = rect.bottom; } } } } } if (m_Ascent == 0 && m_Descent == 0) { FX_RECT rect = GetCharBBox('A'); m_Ascent = rect.bottom == rect.top ? m_FontBBox.top : rect.top; rect = GetCharBBox('g'); m_Descent = rect.bottom == rect.top ? m_FontBBox.bottom : rect.bottom; } }
FX_RECT CPDF_CIDFont::GetCharBBox(uint32_t charcode) { if (charcode < 256 && m_CharBBox[charcode].right != -1) return m_CharBBox[charcode]; FX_RECT rect; bool bVert = false; int glyph_index = GlyphFromCharCode(charcode, &bVert); FXFT_Face face = m_Font.GetFace(); if (face) { if (FXFT_Is_Face_Tricky(face)) { int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); if (!err) { FXFT_BBox cbox; FXFT_Glyph glyph; err = FXFT_Get_Glyph(((FXFT_Face)face)->glyph, &glyph); if (!err) { FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); int pixel_size_x = ((FXFT_Face)face)->size->metrics.x_ppem; int pixel_size_y = ((FXFT_Face)face)->size->metrics.y_ppem; if (pixel_size_x == 0 || pixel_size_y == 0) { rect = FX_RECT(cbox.xMin, cbox.yMax, cbox.xMax, cbox.yMin); } else { rect = FX_RECT(cbox.xMin * 1000 / pixel_size_x, cbox.yMax * 1000 / pixel_size_y, cbox.xMax * 1000 / pixel_size_x, cbox.yMin * 1000 / pixel_size_y); } rect.top = std::min(rect.top, static_cast<int>(FXFT_Get_Face_Ascender(face))); rect.bottom = std::max( rect.bottom, static_cast<int>(FXFT_Get_Face_Descender(face))); FXFT_Done_Glyph(glyph); } } } else { int err = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_SCALE); if (err == 0) { rect = FX_RECT(TT2PDF(FXFT_Get_Glyph_HoriBearingX(face), face), TT2PDF(FXFT_Get_Glyph_HoriBearingY(face), face), TT2PDF(FXFT_Get_Glyph_HoriBearingX(face) + FXFT_Get_Glyph_Width(face), face), TT2PDF(FXFT_Get_Glyph_HoriBearingY(face) - FXFT_Get_Glyph_Height(face), face)); rect.top += rect.top / 64; } } } if (!m_pFontFile && m_Charset == CIDSET_JAPAN1) { uint16_t CID = CIDFromCharCode(charcode); const uint8_t* pTransform = GetCIDTransform(CID); if (pTransform && !bVert) { CFX_Matrix matrix(CIDTransformToFloat(pTransform[0]), CIDTransformToFloat(pTransform[1]), CIDTransformToFloat(pTransform[2]), CIDTransformToFloat(pTransform[3]), CIDTransformToFloat(pTransform[4]) * 1000, CIDTransformToFloat(pTransform[5]) * 1000); CFX_FloatRect rect_f(rect); matrix.TransformRect(rect_f); rect = rect_f.GetOuterRect(); } } if (charcode < 256) m_CharBBox[charcode] = rect; return rect; }