diff options
Diffstat (limited to 'WebCore/platform/graphics/GlyphPageTreeNode.cpp')
-rw-r--r-- | WebCore/platform/graphics/GlyphPageTreeNode.cpp | 97 |
1 files changed, 90 insertions, 7 deletions
diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 53c94b8..6b9d23d 100644 --- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -65,6 +65,31 @@ GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber) return node; } +size_t GlyphPageTreeNode::treeGlyphPageCount() +{ + size_t count = 0; + if (roots) { + HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); + for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) + count += it->second->pageCount(); + } + + if (pageZeroRoot) + count += pageZeroRoot->pageCount(); + + return count; +} + +size_t GlyphPageTreeNode::pageCount() const +{ + size_t count = m_page && m_page->owner() == this ? 1 : 0; + HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end(); + for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it) + count += it->second->pageCount(); + + return count; +} + void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData) { // Enumerate all the roots and prune any tree that contains our custom font data. @@ -78,6 +103,18 @@ void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData) pageZeroRoot->pruneCustomFontData(fontData); } +void GlyphPageTreeNode::pruneTreeFontData(const SimpleFontData* fontData) +{ + if (roots) { + HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); + for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) + it->second->pruneFontData(fontData); + } + + if (pageZeroRoot) + pageZeroRoot->pruneFontData(fontData); +} + GlyphPageTreeNode::~GlyphPageTreeNode() { deleteAllValues(m_children); @@ -146,7 +183,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } } - m_page = new GlyphPage(this); + m_page = GlyphPage::create(this); // Now that we have a buffer full of characters, we want to get back an array // of glyph indices. This part involves calling into the platform-specific @@ -160,19 +197,32 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData); unsigned numRanges = segmentedFontData->numRanges(); bool zeroFilled = false; + RefPtr<GlyphPage> scratchPage; + GlyphPage* pageToFill = m_page.get(); for (unsigned i = 0; i < numRanges; i++) { const FontDataRange& range = segmentedFontData->rangeAt(i); int from = max(0, range.from() - static_cast<int>(start)); int to = 1 + min(range.to() - static_cast<int>(start), static_cast<int>(GlyphPage::size) - 1); if (from < static_cast<int>(GlyphPage::size) && to > 0) { + if (haveGlyphs && !scratchPage) { + scratchPage = GlyphPage::create(this); + pageToFill = scratchPage.get(); + } + if (!zeroFilled) { if (from > 0 || to < static_cast<int>(GlyphPage::size)) { for (unsigned i = 0; i < GlyphPage::size; i++) - m_page->setGlyphDataForIndex(i, 0, 0); + pageToFill->setGlyphDataForIndex(i, 0, 0); } zeroFilled = true; } - haveGlyphs |= m_page->fill(from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); + haveGlyphs |= pageToFill->fill(from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); + if (scratchPage) { + for (int j = from; j < to; j++) { + if (!m_page->m_glyphs[j].glyph && pageToFill->m_glyphs[j].glyph) + m_page->m_glyphs[j] = pageToFill->m_glyphs[j]; + } + } } } } else @@ -208,7 +258,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu m_page = parentPage; } else { // Combine the parent's glyphs and ours to form a new more complete page. - m_page = new GlyphPage(this); + m_page = GlyphPage::create(this); // Overlay the parent page on the fallback page. Check if the fallback font // has added anything. @@ -231,7 +281,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } } } else { - m_page = new GlyphPage(this); + m_page = GlyphPage::create(this); // System fallback. Initialized with the parent's page here, as individual // entries may use different fonts depending on character. If the Font // ever finds it needs a glyph out of the system fallback page, it will @@ -264,9 +314,10 @@ GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigne #ifndef NDEBUG child->m_pageNumber = m_pageNumber; #endif - if (fontData) + if (fontData) { m_children.set(fontData, child); - else { + fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level)); + } else { m_systemFallbackChild = child; child->m_isSystemFallback = true; } @@ -298,4 +349,36 @@ void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData) it->second->pruneCustomFontData(fontData); } +void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level) +{ + ASSERT(fontData); + if (!fontData) + return; + + // Prune any branch that contains this FontData. + HashMap<const FontData*, GlyphPageTreeNode*>::iterator child = m_children.find(fontData); + if (child == m_children.end()) { + // If there is no level-1 node for fontData, then there is no deeper node for it in this tree. + if (!level) + return; + } else { + GlyphPageTreeNode* node = child->second; + m_children.remove(fontData); + unsigned customFontCount = node->m_customFontCount; + delete node; + if (customFontCount) { + for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) + curr->m_customFontCount -= customFontCount; + } + } + + level++; + if (level > fontData->maxGlyphPageTreeLevel()) + return; + + HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); + for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) + it->second->pruneFontData(fontData, level); +} + } |