CPDF_Type3Char* CPDF_Type3Font::LoadChar(uint32_t charcode, int level) { if (level >= _FPDF_MAX_TYPE3_FORM_LEVEL_) return nullptr; auto it = m_CacheMap.find(charcode); if (it != m_CacheMap.end()) return it->second; const FX_CHAR* name = GetAdobeCharName(m_BaseEncoding, m_pCharNames, charcode); if (!name) return nullptr; CPDF_Stream* pStream = ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectBy(name) : nullptr); if (!pStream) return nullptr; std::unique_ptr<CPDF_Type3Char> pNewChar(new CPDF_Type3Char(new CPDF_Form( m_pDocument, m_pFontResources ? m_pFontResources : m_pPageResources, pStream, nullptr))); // This can trigger recursion into this method. The content of |m_CacheMap| // can change as a result. Thus after it returns, check the cache again for // a cache hit. pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), level + 1); it = m_CacheMap.find(charcode); if (it != m_CacheMap.end()) return it->second; FX_FLOAT scale = m_FontMatrix.GetXUnit(); pNewChar->m_Width = (int32_t)(pNewChar->m_Width * scale + 0.5f); FX_RECT& rcBBox = pNewChar->m_BBox; CFX_FloatRect char_rect( (FX_FLOAT)rcBBox.left / 1000.0f, (FX_FLOAT)rcBBox.bottom / 1000.0f, (FX_FLOAT)rcBBox.right / 1000.0f, (FX_FLOAT)rcBBox.top / 1000.0f); if (rcBBox.right <= rcBBox.left || rcBBox.bottom >= rcBBox.top) char_rect = pNewChar->m_pForm->CalcBoundingBox(); char_rect.Transform(&m_FontMatrix); rcBBox.left = FXSYS_round(char_rect.left * 1000); rcBBox.right = FXSYS_round(char_rect.right * 1000); rcBBox.top = FXSYS_round(char_rect.top * 1000); rcBBox.bottom = FXSYS_round(char_rect.bottom * 1000); ASSERT(!pdfium::ContainsKey(m_CacheMap, charcode)); CPDF_Type3Char* pCachedChar = pNewChar.release(); m_CacheMap[charcode] = pCachedChar; if (pCachedChar->m_pForm->GetPageObjectList()->empty()) pCachedChar->m_pForm.reset(); return pCachedChar; }
HudMainPanel::HudMainPanel(const FRect &rect) :HudLayer(rect) { float2 bottom_left(spacing, rect.height() - spacing); FRect char_rect(s_hud_char_icon_size); char_rect += bottom_left - float2(0, char_rect.height()); FRect weapon_rect(s_hud_weapon_size); weapon_rect += float2(char_rect.max.x + spacing, bottom_left.y - weapon_rect.height()); m_hud_char_icon = make_shared<HudCharIcon>(char_rect); m_hud_weapon = make_shared<HudWeapon>(weapon_rect); { FRect stance_rect(s_hud_stance_size); stance_rect += float2(weapon_rect.max.x + spacing, bottom_left.y - s_hud_stance_size.y); for(int n = 0; n < arraySize(s_stance_buttons); n++) { PHudButton stance(new HudRadioButton(stance_rect, (int)s_stance_buttons[n].stance_id, 1)); stance->setIcon(s_stance_buttons[n].icon_id); m_hud_stances.push_back(std::move(stance)); stance_rect += float2(0.0f, -s_hud_stance_size.y - spacing); } } { FRect button_rect = align(FRect(s_hud_button_size), char_rect, align_top, spacing); button_rect += float2(char_rect.min.x - button_rect.min.x, 0.0f); for(int n = 0; n < arraySize(s_buttons); n++) { PHudButton button(new HudToggleButton(button_rect, s_buttons[n].layer_id)); button->setLabel(s_buttons[n].name); m_hud_buttons.emplace_back(std::move(button)); button_rect += float2(button_rect.width() + spacing, 0.0f); } } attach(m_hud_weapon); attach(m_hud_char_icon); for(int n = 0; n < (int)m_hud_buttons.size(); n++) attach(m_hud_buttons[n]); for(int n = 0; n < (int)m_hud_stances.size(); n++) attach(m_hud_stances[n]); }