Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(399)

Unified Diff: webkit/pending/Font.cpp

Issue 6500: Cleaning up the unfork (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/pending/FileSystemWin.cpp ('k') | webkit/pending/FontCache.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/pending/Font.cpp
===================================================================
--- webkit/pending/Font.cpp (revision 2884)
+++ webkit/pending/Font.cpp (working copy)
@@ -1,839 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "Font.h"
-
-#include "CharacterNames.h"
-#include "FloatRect.h"
-#include "FontCache.h"
-#include "FontFallbackList.h"
-#include "IntPoint.h"
-#include "GlyphBuffer.h"
-#include <wtf/unicode/Unicode.h>
-#include <wtf/MathExtras.h>
-
-#if USE(ICU_UNICODE)
-#include <unicode/unorm.h>
-#endif
-
-using namespace WTF;
-using namespace Unicode;
-
-namespace WebCore {
-
-// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
-const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
-
-const uint8_t Font::gRoundingHackCharacterTable[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-Font::CodePath Font::codePath = Auto;
-
-struct WidthIterator {
- WidthIterator(const Font* font, const TextRun& run);
-
- void advance(int to, GlyphBuffer* glyphBuffer = 0);
- bool advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer = 0);
-
- const Font* m_font;
-
- const TextRun& m_run;
- int m_end;
-
- unsigned m_currentCharacter;
- float m_runWidthSoFar;
- float m_padding;
- float m_padPerSpace;
- float m_finalRoundingWidth;
-
-private:
- UChar32 normalizeVoicingMarks(int currentCharacter);
-};
-
-WidthIterator::WidthIterator(const Font* font, const TextRun& run)
- : m_font(font)
- , m_run(run)
- , m_end(run.length())
- , m_currentCharacter(0)
- , m_runWidthSoFar(0)
- , m_finalRoundingWidth(0)
-{
- // If the padding is non-zero, count the number of spaces in the run
- // and divide that by the padding for per space addition.
- m_padding = m_run.padding();
- if (!m_padding)
- m_padPerSpace = 0;
- else {
- float numSpaces = 0;
- for (int i = 0; i < run.length(); i++)
- if (Font::treatAsSpace(m_run[i]))
- numSpaces++;
-
- if (numSpaces == 0)
- m_padPerSpace = 0;
- else
- m_padPerSpace = ceilf(m_run.padding() / numSpaces);
- }
-}
-
-void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
-{
- if (offset > m_end)
- offset = m_end;
-
- int currentCharacter = m_currentCharacter;
- const UChar* cp = m_run.data(currentCharacter);
-
- bool rtl = m_run.rtl();
- bool hasExtraSpacing = m_font->letterSpacing() || m_font->wordSpacing() || m_padding;
-
- float runWidthSoFar = m_runWidthSoFar;
- float lastRoundingWidth = m_finalRoundingWidth;
-
- while (currentCharacter < offset) {
- UChar32 c = *cp;
- unsigned clusterLength = 1;
- if (c >= 0x3041) {
- if (c <= 0x30FE) {
- // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
- // Normalize into composed form, and then look for glyph with base + combined mark.
- // Check above for character range to minimize performance impact.
- UChar32 normalized = normalizeVoicingMarks(currentCharacter);
- if (normalized) {
- c = normalized;
- clusterLength = 2;
- }
- } else if (U16_IS_SURROGATE(c)) {
- if (!U16_IS_SURROGATE_LEAD(c))
- break;
-
- // Do we have a surrogate pair? If so, determine the full Unicode (32 bit)
- // code point before glyph lookup.
- // Make sure we have another character and it's a low surrogate.
- if (currentCharacter + 1 >= m_run.length())
- break;
- UChar low = cp[1];
- if (!U16_IS_TRAIL(low))
- break;
- c = U16_GET_SUPPLEMENTARY(c, low);
- clusterLength = 2;
- }
- }
-
- const GlyphData& glyphData = m_font->glyphDataForCharacter(c, rtl);
- Glyph glyph = glyphData.glyph;
- const SimpleFontData* fontData = glyphData.fontData;
-
- ASSERT(fontData);
-
- // Now that we have a glyph and font data, get its width.
- float width;
- if (c == '\t' && m_run.allowTabs()) {
- float tabWidth = m_font->tabWidth();
- width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth);
- } else {
- width = fontData->widthForGlyph(glyph);
- // We special case spaces in two ways when applying word rounding.
- // First, we round spaces to an adjusted width in all fonts.
- // Second, in fixed-pitch fonts we ensure that all characters that
- // match the width of the space character have the same width as the space character.
- if (width == fontData->m_spaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())
- width = fontData->m_adjustedSpaceWidth;
- }
-
- if (hasExtraSpacing && !m_run.spacingDisabled()) {
- // Account for letter-spacing.
- if (width && m_font->letterSpacing())
- width += m_font->letterSpacing();
-
- if (Font::treatAsSpace(c)) {
- // Account for padding. WebCore uses space padding to justify text.
- // We distribute the specified padding over the available spaces in the run.
- if (m_padding) {
- // Use left over padding if not evenly divisible by number of spaces.
- if (m_padding < m_padPerSpace) {
- width += m_padding;
- m_padding = 0;
- } else {
- width += m_padPerSpace;
- m_padding -= m_padPerSpace;
- }
- }
-
- // Account for word spacing.
- // We apply additional space between "words" by adding width to the space character.
- if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
- width += m_font->wordSpacing();
- }
- }
-
- // Advance past the character we just dealt with.
- cp += clusterLength;
- currentCharacter += clusterLength;
-
- // Account for float/integer impedance mismatch between CG and KHTML. "Words" (characters
- // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
- // We adjust the width of the last character of a "word" to ensure an integer width.
- // If we move KHTML to floats we can remove this (and related) hacks.
-
- float oldWidth = width;
-
- // Force characters that are used to determine word boundaries for the rounding hack
- // to be integer width, so following words will start on an integer boundary.
- if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(c))
- width = ceilf(width);
-
- // Check to see if the next character is a "rounding hack character", if so, adjust
- // width so that the total run width will be on an integer boundary.
- if ((m_run.applyWordRounding() && currentCharacter < m_run.length() && Font::isRoundingHackCharacter(*cp))
- || (m_run.applyRunRounding() && currentCharacter >= m_end)) {
- float totalWidth = runWidthSoFar + width;
- width += ceilf(totalWidth) - totalWidth;
- }
-
- runWidthSoFar += width;
-
- if (glyphBuffer)
- glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width));
-
- lastRoundingWidth = width - oldWidth;
- }
-
- m_currentCharacter = currentCharacter;
- m_runWidthSoFar = runWidthSoFar;
- m_finalRoundingWidth = lastRoundingWidth;
-}
-
-bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
-{
- glyphBuffer->clear();
- advance(m_currentCharacter + 1, glyphBuffer);
- float w = 0;
- for (int i = 0; i < glyphBuffer->size(); ++i)
- w += glyphBuffer->advanceAt(i);
- width = w;
- return !glyphBuffer->isEmpty();
-}
-
-UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
-{
- if (currentCharacter + 1 < m_end) {
- if (combiningClass(m_run[currentCharacter + 1]) == hiraganaKatakanaVoicingMarksCombiningClass) {
-#if USE(ICU_UNICODE)
- // Normalize into composed form using 3.2 rules.
- UChar normalizedCharacters[2] = { 0, 0 };
- UErrorCode uStatus = U_ZERO_ERROR;
- int32_t resultLength = unorm_normalize(m_run.data(currentCharacter), 2,
- UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
- if (resultLength == 1 && uStatus == 0)
- return normalizedCharacters[0];
-#elif USE(QT4_UNICODE)
- QString tmp(reinterpret_cast<const QChar*>(m_run.data(currentCharacter)), 2);
- QString res = tmp.normalized(QString::NormalizationForm_C, QChar::Unicode_3_2);
- if (res.length() == 1)
- return res.at(0).unicode();
-#endif
- }
- }
- return 0;
-}
-
-// ============================================================================================
-// Font Implementation (Cross-Platform Portion)
-// ============================================================================================
-
-Font::Font()
- : m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(false)
-{
-}
-
-Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
- : m_fontDescription(fd)
- , m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(letterSpacing)
- , m_wordSpacing(wordSpacing)
- , m_isPlatformFont(false)
-{
-}
-
-Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
- : m_fontList(FontFallbackList::create())
- , m_pageZero(0)
- , m_cachedPrimaryFont(0)
- , m_letterSpacing(0)
- , m_wordSpacing(0)
- , m_isPlatformFont(true)
-{
- m_fontDescription.setUsePrinterFont(isPrinterFont);
- m_fontList->setPlatformFont(fontData);
-}
-
-Font::Font(const Font& other)
- : m_fontDescription(other.m_fontDescription)
- , m_fontList(other.m_fontList)
- , m_pages(other.m_pages)
- , m_pageZero(other.m_pageZero)
- , m_cachedPrimaryFont(other.m_cachedPrimaryFont)
- , m_letterSpacing(other.m_letterSpacing)
- , m_wordSpacing(other.m_wordSpacing)
- , m_isPlatformFont(other.m_isPlatformFont)
-{
-}
-
-Font& Font::operator=(const Font& other)
-{
- m_fontDescription = other.m_fontDescription;
- m_fontList = other.m_fontList;
- m_pages = other.m_pages;
- m_pageZero = other.m_pageZero;
- m_cachedPrimaryFont = other.m_cachedPrimaryFont;
- m_letterSpacing = other.m_letterSpacing;
- m_wordSpacing = other.m_wordSpacing;
- m_isPlatformFont = other.m_isPlatformFont;
- return *this;
-}
-
-Font::~Font()
-{
-}
-
-bool Font::operator==(const Font& other) const
-{
- // Our FontData don't have to be checked, since checking the font description will be fine.
- // FIXME: This does not work if the font was made with the FontPlatformData constructor.
- if ((m_fontList && m_fontList->loadingCustomFonts()) ||
- (other.m_fontList && other.m_fontList->loadingCustomFonts()))
- return false;
-
- FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
- FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
-
- return first == second
- && m_fontDescription == other.m_fontDescription
- && m_letterSpacing == other.m_letterSpacing
- && m_wordSpacing == other.m_wordSpacing
- && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
-}
-
-const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
-{
- bool useSmallCapsFont = forceSmallCaps;
- if (m_fontDescription.smallCaps()) {
- UChar32 upperC = Unicode::toUpper(c);
- if (upperC != c) {
- c = upperC;
- useSmallCapsFont = true;
- }
- }
-
- if (mirror)
- c = mirroredChar(c);
-
- unsigned pageNumber = (c / GlyphPage::size);
-
- GlyphPageTreeNode* node = pageNumber ? m_pages.get(pageNumber) : m_pageZero;
- if (!node) {
- node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
-
- GlyphPage* page;
- if (!useSmallCapsFont) {
- // Fastest loop, for the common case (not small caps).
- while (true) {
- page = node->page();
- if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- } else {
- while (true) {
- page = node->page();
- if (page) {
- const GlyphData& data = page->glyphDataForCharacter(c);
- if (data.fontData) {
- // The smallCapsFontData function should not normally return 0.
- // But if it does, we will just render the capital letter big.
- const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
- if (!smallCapsFontData)
- return data;
-
- GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
- const GlyphPage* smallCapsPage = smallCapsNode->page();
- if (smallCapsPage) {
- const GlyphData& data = smallCapsPage->glyphDataForCharacter(c);
- if (data.fontData)
- return data;
- }
-
- // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
- // a font has the lowercase character but the small caps font does not have its uppercase version.
- return smallCapsFontData->missingGlyphData();
- }
-
- if (node->isSystemFallback())
- break;
- }
-
- // Proceed with the fallback list.
- node = node->getChild(fontDataAt(node->level()), pageNumber);
- if (pageNumber)
- m_pages.set(pageNumber, node);
- else
- m_pageZero = node;
- }
- }
-
- ASSERT(page);
- ASSERT(node->isSystemFallback());
-
- // System fallback is character-dependent. When we get here, we
- // know that the character in question isn't in the system fallback
- // font's glyph page. Try to lazily create it here.
- UChar codeUnits[2];
- int codeUnitsLength;
- if (c <= 0xFFFF) {
- UChar c16 = c;
- if (Font::treatAsSpace(c16))
- codeUnits[0] = ' ';
- else if (Font::treatAsZeroWidthSpace(c16))
- codeUnits[0] = zeroWidthSpace;
- else
- codeUnits[0] = c16;
- codeUnitsLength = 1;
- } else {
- codeUnits[0] = U16_LEAD(c);
- codeUnits[1] = U16_TRAIL(c);
- codeUnitsLength = 2;
- }
- const SimpleFontData* characterFontData = FontCache::getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
- if (useSmallCapsFont)
- characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
- if (characterFontData) {
- // Got the fallback glyph and font.
- GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
- const GlyphData& data = fallbackPage && fallbackPage->glyphDataForCharacter(c).fontData ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
- // Cache it so we don't have to do system fallback again next time.
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
- }
-
- // Even system fallback can fail; use the missing glyph in that case.
- // FIXME: It would be nicer to use the missing glyph from the last resort font instead.
- const GlyphData& data = primaryFont()->missingGlyphData();
- if (!useSmallCapsFont)
- page->setGlyphDataForCharacter(c, data.glyph, data.fontData);
- return data;
-}
-
-void Font::cachePrimaryFont() const
-{
- ASSERT(m_fontList);
- ASSERT(!m_cachedPrimaryFont);
- m_cachedPrimaryFont = m_fontList->primaryFont(this)->fontDataForCharacter(' ');
-}
-
-const FontData* Font::fontDataAt(unsigned index) const
-{
- ASSERT(m_fontList);
- return m_fontList->fontDataAt(this, index);
-}
-
-const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
-{
- ASSERT(m_fontList);
- return m_fontList->fontDataForCharacters(this, characters, length);
-}
-
-void Font::update(PassRefPtr<FontSelector> fontSelector) const
-{
- // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
- // being reasonably safe (because inherited fonts in the render tree pick up the new
- // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
- // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
- // and could eventually be rectified by using RefPtrs for Fonts themselves.
- if (!m_fontList)
- m_fontList = FontFallbackList::create();
- m_fontList->invalidate(fontSelector);
- m_cachedPrimaryFont = 0;
- m_pageZero = 0;
- m_pages.clear();
-}
-
-int Font::width(const TextRun& run) const
-{
- return lroundf(floatWidth(run));
-}
-
-int Font::ascent() const
-{
- return primaryFont()->ascent();
-}
-
-int Font::descent() const
-{
- return primaryFont()->descent();
-}
-
-int Font::lineSpacing() const
-{
- return primaryFont()->lineSpacing();
-}
-
-int Font::lineGap() const
-{
- return primaryFont()->lineGap();
-}
-
-float Font::xHeight() const
-{
- return primaryFont()->xHeight();
-}
-
-unsigned Font::unitsPerEm() const
-{
- return primaryFont()->unitsPerEm();
-}
-
-int Font::spaceWidth() const
-{
- return (int)ceilf(primaryFont()->m_adjustedSpaceWidth + m_letterSpacing);
-}
-
-bool Font::isFixedPitch() const
-{
- ASSERT(m_fontList);
- return m_fontList->isFixedPitch(this);
-}
-
-void Font::setCodePath(CodePath p)
-{
- codePath = p;
-}
-
-bool Font::canUseGlyphCache(const TextRun& run) const
-{
- switch (codePath) {
- case Auto:
- break;
- case Simple:
- return true;
- case Complex:
- return false;
- }
-
- // Start from 0 since drawing and highlighting also measure the characters before run->from
- for (int i = 0; i < run.length(); i++) {
- const UChar c = run[i];
- if (c < 0x300) // U+0300 through U+036F Combining diacritical marks
- continue;
- if (c <= 0x36F)
- return false;
-
- if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
- continue;
- if (c <= 0x05CF)
- return false;
-
- if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
- continue;
- if (c <= 0x1059)
- return false;
-
- if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
- continue;
- if (c <= 0x11FF)
- return false;
-
- if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian
- continue;
- if (c <= 0x18AF)
- return false;
-
- if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0)
- continue;
- if (c <= 0x194F)
- return false;
-
- if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols
- continue;
- if (c <= 0x20FF)
- return false;
-
- if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks
- continue;
- if (c <= 0xFE2F)
- return false;
- }
-
- return true;
-
-}
-
-void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- // This glyph buffer holds our glyphs+advances+font data for each glyph.
- GlyphBuffer glyphBuffer;
-
- float startX = point.x();
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
- if (glyphBuffer.isEmpty())
- return;
-
- float afterWidth = it.m_runWidthSoFar;
-
- if (run.rtl()) {
- float finalRoundingWidth = it.m_finalRoundingWidth;
- it.advance(run.length());
- startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
- } else
- startX += beforeWidth;
-
- // Swap the order of the glyphs if right-to-left.
- if (run.rtl())
- for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
- glyphBuffer.swap(i, end);
-
- // Calculate the starting point of the glyphs to be displayed by adding
- // all the advances up to the first glyph.
- FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
-}
-
-void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer,
- const TextRun& run, const FloatPoint& point) const
-{
- // Draw each contiguous run of glyphs that use the same font data.
- const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
- FloatSize offset = glyphBuffer.offsetAt(0);
- FloatPoint startPoint(point);
- float nextX = startPoint.x();
- int lastFrom = 0;
- int nextGlyph = 0;
- while (nextGlyph < glyphBuffer.size()) {
- const SimpleFontData* nextFontData = glyphBuffer.fontDataAt(nextGlyph);
- FloatSize nextOffset = glyphBuffer.offsetAt(nextGlyph);
- if (nextFontData != fontData || nextOffset != offset) {
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-
- lastFrom = nextGlyph;
- fontData = nextFontData;
- offset = nextOffset;
- startPoint.setX(nextX);
- }
- nextX += glyphBuffer.advanceAt(nextGlyph);
- nextGlyph++;
- }
-
- drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
-}
-
-void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- // Don't draw anything while we are using custom fonts that are in the process of loading.
- if (m_fontList && m_fontList->loadingCustomFonts())
- return;
-
- to = (to == -1 ? run.length() : to);
-
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont()) {
- drawTextUsingSVGFont(context, run, point, from, to);
- return;
- }
-#endif
-
- if (canUseGlyphCache(run))
- drawSimpleText(context, run, point, from, to);
- else
- drawComplexText(context, run, point, from, to);
-}
-
-float Font::floatWidth(const TextRun& run) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return floatWidthUsingSVGFont(run);
-#endif
-
- if (canUseGlyphCache(run))
- return floatWidthForSimpleText(run, 0);
- return floatWidthForComplexText(run);
-}
-
-float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
-#endif
-
- charsConsumed = run.length();
- glyphName = "";
- if (canUseGlyphCache(run))
- return floatWidthForSimpleText(run, 0);
- return floatWidthForComplexText(run);
-}
-
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer) const
-{
- WidthIterator it(this, run);
- it.advance(run.length(), glyphBuffer);
- return it.m_runWidthSoFar;
-}
-
-FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return selectionRectForTextUsingSVGFont(run, point, h, from, to);
-#endif
-
- to = (to == -1 ? run.length() : to);
- if (canUseGlyphCache(run))
- return selectionRectForSimpleText(run, point, h, from, to);
- return selectionRectForComplexText(run, point, h, from, to);
-}
-
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
- WidthIterator it(this, run);
- it.advance(from);
- float beforeWidth = it.m_runWidthSoFar;
- it.advance(to);
- float afterWidth = it.m_runWidthSoFar;
-
- // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
- if (run.rtl()) {
- it.advance(run.length());
- float totalWidth = it.m_runWidthSoFar;
- return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
- } else {
- return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
- }
-}
-
-int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
-{
-#if ENABLE(SVG_FONTS)
- if (primaryFont()->isSVGFont())
- return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
-#endif
-
- if (canUseGlyphCache(run))
- return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
- return offsetForPositionForComplexText(run, x, includePartialGlyphs);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const
-{
- float delta = (float)x;
-
- WidthIterator it(this, run);
- GlyphBuffer localGlyphBuffer;
- unsigned offset;
- if (run.rtl()) {
- delta -= floatWidthForSimpleText(run, 0);
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta += w;
- if (includePartialGlyphs) {
- if (delta - w / 2 >= 0)
- break;
- } else {
- if (delta >= 0)
- break;
- }
- }
- } else {
- while (1) {
- offset = it.m_currentCharacter;
- float w;
- if (!it.advanceOneCharacter(w, &localGlyphBuffer))
- break;
- delta -= w;
- if (includePartialGlyphs) {
- if (delta + w / 2 <= 0)
- break;
- } else {
- if (delta <= 0)
- break;
- }
- }
- }
-
- return offset;
-}
-
-#if ENABLE(SVG_FONTS)
-bool Font::isSVGFont() const
-{
- return primaryFont()->isSVGFont();
-}
-#endif
-
-FontSelector* Font::fontSelector() const
-{
- return m_fontList ? m_fontList->fontSelector() : 0;
-}
-
-}
« no previous file with comments | « webkit/pending/FileSystemWin.cpp ('k') | webkit/pending/FontCache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698