summaryrefslogtreecommitdiffstats
path: root/WebKit/android/nav/CacheBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/nav/CacheBuilder.cpp')
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp211
1 files changed, 105 insertions, 106 deletions
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 4acf598..f854e71 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -13,7 +13,7 @@
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -42,6 +42,7 @@
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLSelectElement.h"
+#include "HTMLTextAreaElement.h"
#include "InlineTextBox.h"
#include "KURL.h"
#include "PluginView.h"
@@ -93,14 +94,11 @@ Frame* CacheBuilder::FrameAnd(const CacheBuilder* cacheBuilder) {
#if DUMP_NAV_CACHE
static bool hasEventListener(Node* node, const AtomicString& eventType) {
- const RegisteredEventListenerVector& listeners = node->eventListeners();
- size_t size = listeners.size();
- for (size_t i = 0; i < size; ++i) {
- const RegisteredEventListener& r = *listeners[i];
- if (r.eventType() == eventType)
- return true;
- }
- return false;
+ if (!node->isElementNode())
+ return false;
+ Element* element = static_cast<Element*>(node);
+ EventListener* listener = element->getAttributeEventListener(eventType);
+ return 0 != listener;
}
#define DEBUG_BUFFER_SIZE 256
@@ -143,7 +141,9 @@ void CacheBuilder::Debug::flush() {
break;
len++;
}
- while (mBuffer[len] == '\\' || mBuffer[len] == '"')
+ while (len > 0 && mBuffer[len - 1] == '\\')
+ len--;
+ while (mBuffer[len] == '"')
len++;
}
const char* prefix = mPrefix;
@@ -349,8 +349,11 @@ void CacheBuilder::Debug::groups() {
} while ((node = node->traverseNextNode()) != NULL);
int focusIndex = -1;
if (atLeastOne == false) {
- DUMP_NAV_LOGD("#define TEST%s_RECTS NULL\n", name);
- DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = 0; // no focusable nodes\n", name);
+ DUMP_NAV_LOGD("static DebugTestNode TEST%s_RECTS[] = {\n"
+ "{{0, 0, 0, 0}, \"\", 0, -1, \"\", {0, 0, 0, 0}, false, 0}\n"
+ "};\n\n", name);
+ DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = 1;"
+ " // no focusable nodes\n", name);
DUMP_NAV_LOGD("#define TEST%s_RECTPARTS NULL\n", name);
} else {
node = doc;
@@ -435,6 +438,7 @@ void CacheBuilder::Debug::groups() {
snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s"
", %d},",absB.x(), absB.y(), absB.width(), absB.height(),
renderer->hasOverflowClip() ? "true" : "false", tabindex);
+ // TODO: add renderer->style()->visibility()
print(scratch);
} else
print(", {0, 0, 0, 0}, false, 0},");
@@ -547,7 +551,7 @@ void CacheBuilder::Debug::groups() {
int contentsHeight = layer->height();
DUMP_NAV_LOGD("static int TEST%s_FOCUS = %d;\n", name, focusIndex);
DUMP_NAV_LOGD("static int TEST%s_WIDTH = %d;\n", name, contentsWidth);
- DUMP_NAV_LOGD("static int TEST%s_HEIGHT = %d;\n", name, contentsHeight);
+ DUMP_NAV_LOGD("static int TEST%s_HEIGHT = %d;\n\n", name, contentsHeight);
}
bool CacheBuilder::Debug::isFocusable(Node* node) {
@@ -721,7 +725,7 @@ void CacheBuilder::Debug::wideString(const String& str) {
CacheBuilder::CacheBuilder()
{
- mAllowableTypes = ALL_CACHEDNODETYPES;
+ mAllowableTypes = ALL_CACHEDNODE_BITS;
#ifdef DUMP_NAV_CACHE_USING_PRINTF
gNavCacheLogFile = NULL;
#endif
@@ -756,14 +760,9 @@ void CacheBuilder::adjustForColumns(const ClipColumnTracker& track,
// Checks if a node has one of event listener types.
bool CacheBuilder::NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length) {
- const RegisteredEventListenerVector& listeners = node->eventListeners();
- size_t size = listeners.size();
- for (size_t i = 0; i < size; ++i) {
- const RegisteredEventListener& r = *listeners[i];
- for (int j = 0; j < length; ++j) {
- if (r.eventType() == eventTypes[j])
- return true;
- }
+ for (int i = 0; i < length; ++i) {
+ if (!node->getEventListeners(eventTypes[i]).isEmpty())
+ return true;
}
return false;
}
@@ -825,6 +824,16 @@ void CacheBuilder::buildCache(CachedRoot* root)
setData((CachedFrame*) root);
}
+static Node* ParentWithChildren(Node* node)
+{
+ Node* parent = node;
+ while ((parent = parent->parentNode())) {
+ if (parent->childNodeCount() > 1)
+ return parent;
+ }
+ return 0;
+}
+
static Node* OneAfter(Node* node)
{
Node* parent = node;
@@ -900,6 +909,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
cachedFrame->add(cachedParentNode);
Node* node = parent;
int cacheIndex = 1;
+ int textInputIndex = 0;
Node* focused = doc->focusedNode();
if (focused)
cachedRoot->setFocusBounds(focused->getRect());
@@ -918,8 +928,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
lastChildIndex = last->mCachedNodeIndex;
last = &tracker.last();
}
- if (node == last->mParentLastChild)
- last->mParentLastChild = NULL;
do {
const ClipColumnTracker* lastClip = &clipTracker.last();
if (node != lastClip->mLastChild)
@@ -946,7 +954,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
cachedFrame->addFrame(cachedChild);
cachedNode.init(node);
cachedNode.setIndex(cacheIndex++);
- cachedNode.setChildFrameIndex(childFrameIndex);
+ cachedNode.setDataIndex(childFrameIndex);
+ cachedNode.setType(FRAME_CACHEDNODETYPE);
#if DUMP_NAV_CACHE
cachedNode.mDebug.mNodeIndex = nodeIndex;
cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex(
@@ -986,27 +995,19 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
bool computeCursorRings = false;
bool hasClip = false;
bool hasMouseOver = false;
- bool isAnchor = false;
- bool isArea = node->hasTagName(HTMLNames::areaTag);
- bool isPassword = false;
- bool isTextArea = false;
- bool isTextField = false;
- bool isRtlText = false;
bool isUnclipped = false;
bool isFocus = node == focused;
bool takesFocus = false;
- bool wantsKeyEvents = false;
- int maxLength = -1;
- int textSize = 12;
int columnGap = 0;
TextDirection direction = LTR;
- String name;
String exported;
CachedNodeType type = NORMAL_CACHEDNODETYPE;
+ CachedInput cachedInput;
IntRect bounds;
IntRect absBounds;
WTF::Vector<IntRect>* columns = NULL;
- if (isArea) {
+ if (node->hasTagName(HTMLNames::areaTag)) {
+ type = AREA_CACHEDNODETYPE;
HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
bounds = getAreaRect(area);
bounds.move(globalOffsetX, globalOffsetY);
@@ -1028,7 +1029,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
bounds = absBounds;
isUnclipped = true;
takesFocus = true;
- wantsKeyEvents = true;
+ type = PLUGIN_CACHEDNODETYPE;
goto keepNode;
}
if (nodeRenderer->isRenderBlock()) {
@@ -1052,11 +1053,11 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
clip.mHasClip = hasClip;
clip.mDirection = direction;
if (columns != NULL) {
- const IntRect& oRect = ((RenderBox*)nodeRenderer)->overflowRect(true);
+ const IntRect& oRect = ((RenderBox*)nodeRenderer)->visibleOverflowRect();
clip.mBounds.move(oRect.x(), oRect.y());
}
}
- if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODETYPE) {
+ if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODE_BITS) {
if (last->mSomeParentTakesFocus) // don't look at text inside focusable node
continue;
CachedNodeType checkType;
@@ -1072,7 +1073,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
DUMP_NAV_LOGD("%s\n", buffer);
}
#endif
- type = (CachedNodeType) checkType;
+ type = checkType;
// !!! test ! is the following line correctly needed for frames to work?
cachedNode.init(node);
const ClipColumnTracker& clipTrack = clipTracker.last();
@@ -1096,18 +1097,35 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
}
if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
HTMLInputElement* input = (HTMLInputElement*) node;
- if (input->inputType() == HTMLInputElement::FILE)
+ HTMLInputElement::InputType inputType = input->inputType();
+ if (input->isTextField()) {
+ type = TEXT_INPUT_CACHEDNODETYPE;
+ cachedInput.init();
+ cachedInput.setFormPointer(input->form());
+ cachedInput.setIsTextField(true);
+ cachedInput.setIsReadOnly(input->readOnly());
+ exported = input->value().threadsafeCopy();
+ cachedInput.setMaxLength(input->maxLength());
+ cachedInput.setInputType(inputType);
+ // If this does not need to be threadsafe, we can use crossThreadString().
+ // See http://trac.webkit.org/changeset/49160.
+ cachedInput.setName(input->name().string().threadsafeCopy());
+ // can't detect if this is drawn on top (example: deviant.com login parts)
+ isUnclipped = isTransparent;
+ } else if (inputType == HTMLInputElement::HIDDEN)
continue;
- isTextField = input->isTextField();
- if (isTextField)
- wantsKeyEvents = true;
- isPassword = input->inputType() == HTMLInputElement::PASSWORD;
- maxLength = input->maxLength();
- name = input->name().string().copy();
- isUnclipped = isTransparent; // can't detect if this is drawn on top (example: deviant.com login parts)
- } else if (node->hasTagName(HTMLNames::textareaTag))
- isTextArea = wantsKeyEvents = true;
- else if (node->hasTagName(HTMLNames::aTag)) {
+ } else if (node->hasTagName(HTMLNames::textareaTag)) {
+ cachedInput.init();
+ type = TEXT_INPUT_CACHEDNODETYPE;
+ HTMLTextAreaElement* area = static_cast<HTMLTextAreaElement*>(node);
+ cachedInput.setFormPointer(area->form());
+ cachedInput.setIsReadOnly(area->readOnly());
+ // Although technically it is not an HTMLInputElement, and therefore
+ // has no InputType, this one is the most appropriate.
+ cachedInput.setInputType(HTMLInputElement::TEXT);
+ cachedInput.setIsTextField(false);
+ exported = area->value().threadsafeCopy();
+ } else if (node->hasTagName(HTMLNames::aTag)) {
const HTMLAnchorElement* anchorNode =
(const HTMLAnchorElement*) node;
if (!anchorNode->isFocusable() && !HasTriggerEvent(node))
@@ -1115,32 +1133,31 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
if (node->disabled())
continue;
hasMouseOver = NodeHasEventListeners(node, &eventNames().mouseoverEvent, 1);
- isAnchor = true;
+ type = ANCHOR_CACHEDNODETYPE;
KURL href = anchorNode->href();
if (!href.isEmpty() && !WebCore::protocolIsJavaScript(href.string()))
// Set the exported string for all non-javascript anchors.
- exported = href.string().copy();
+ exported = href.string().threadsafeCopy();
}
- if (isTextField || isTextArea) {
+ if (type == TEXT_INPUT_CACHEDNODETYPE) {
RenderTextControl* renderText =
static_cast<RenderTextControl*>(nodeRenderer);
if (isFocus)
cachedRoot->setSelection(renderText->selectionStart(), renderText->selectionEnd());
- exported = renderText->text().copy();
// FIXME: Would it be better to use (float) size()?
// FIXME: Are we sure there will always be a style and font, and it's correct?
RenderStyle* style = nodeRenderer->style();
if (style) {
isUnclipped |= !style->hasAppearance();
- textSize = style->fontSize();
- isRtlText = style->direction() == RTL ||
- style->textAlign() == WebCore::RIGHT ||
- style->textAlign() == WebCore::WEBKIT_RIGHT;
+ cachedInput.setTextSize(style->fontSize());
+ cachedInput.setIsRtlText(style->direction() == RTL
+ || style->textAlign() == WebCore::RIGHT
+ || style->textAlign() == WebCore::WEBKIT_RIGHT);
}
}
takesFocus = true;
bounds = absBounds;
- if (!isAnchor) {
+ if (type != ANCHOR_CACHEDNODETYPE) {
bool isFocusable = node->isKeyboardFocusable(NULL) ||
node->isMouseFocusable() || node->isFocusable();
if (isFocusable == false) {
@@ -1174,43 +1191,37 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
continue;
}
const IntRect& parentClip = clipTrack.mBounds;
- if (hasClip == false && isAnchor)
+ if (hasClip == false && type == ANCHOR_CACHEDNODETYPE)
clip = parentClip;
else
clip.intersect(parentClip);
hasClip = true;
}
- if (hasClip && !clip.isEmpty() && cachedNode.clip(clip) == false) {
- cachedNode.setBounds(clip);
- cachedNode.cursorRings().append(clip);
- isUnclipped = true;
+ if (hasClip) {
+ if (clip.isEmpty())
+ continue; // skip this node if clip prevents all drawing
+ else if (cachedNode.clip(clip) == false)
+ continue; // skip this node if outside of the clip
}
cachedNode.setNavableRects();
- cachedNode.setChildFrameIndex(-1);
cachedNode.setExport(exported);
cachedNode.setHasCursorRing(hasCursorRing);
cachedNode.setHasMouseOver(hasMouseOver);
cachedNode.setHitBounds(absBounds);
cachedNode.setIndex(cacheIndex);
- cachedNode.setIsAnchor(isAnchor);
- cachedNode.setIsArea(isArea);
cachedNode.setIsFocus(isFocus);
- cachedNode.setIsPassword(isPassword);
- cachedNode.setIsRtlText(isRtlText);
- cachedNode.setIsTextArea(isTextArea);
- cachedNode.setIsTextField(isTextField);
cachedNode.setIsTransparent(isTransparent);
cachedNode.setIsUnclipped(isUnclipped);
- cachedNode.setMaxLength(maxLength);
- cachedNode.setName(name);
cachedNode.setParentIndex(last->mCachedNodeIndex);
- if (last->mParentLastChild == NULL)
- last->mParentLastChild = OneAfter(node->parentNode()->lastChild());
- cachedNode.setParentGroup(last->mParentLastChild);
+ cachedNode.setParentGroup(ParentWithChildren(node));
cachedNode.setTabIndex(tabIndex);
- cachedNode.setTextSize(textSize);
cachedNode.setType(type);
- cachedNode.setWantsKeyEvents(wantsKeyEvents);
+ if (type == TEXT_INPUT_CACHEDNODETYPE) {
+ cachedFrame->add(cachedInput);
+ cachedNode.setDataIndex(textInputIndex);
+ textInputIndex++;
+ } else
+ cachedNode.setDataIndex(-1);
#if DUMP_NAV_CACHE
cachedNode.mDebug.mNodeIndex = nodeIndex;
cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex(
@@ -1228,7 +1239,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
Tracker& working = tracker.last();
working.mCachedNodeIndex = lastIndex;
working.mLastChild = OneAfter(lastChild);
- working.mParentLastChild = OneAfter(node->parentNode()->lastChild());
last = &tracker.at(tracker.size() - 2);
working.mSomeParentTakesFocus = last->mSomeParentTakesFocus | takesFocus;
}
@@ -1672,9 +1682,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
// is that suggested this fix.
// if (s->mWordCount == 0 && s->mContinuationNode)
// return FOUND_NONE;
- s->mBases[s->mWordCount] = baseChars;
- s->mWords[s->mWordCount] = chars - s->mNumberCount;
- s->mStarts[s->mWordCount] = s->mCurrentStart;
+ s->newWord(baseChars, chars);
if (WTF::isASCIILower(ch) && s->mNumberCount == 0)
s->mFirstLower = chars;
s->mNumberCount = 0;
@@ -1722,9 +1730,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
s->mNumberWords >>= ++shift;
if (s->mBases[0] != s->mBases[shift]) // if we're past the original node, bail
break;
- memmove(s->mBases, &s->mBases[shift], (sizeof(s->mBases) / sizeof(s->mBases[0]) - shift) * sizeof(s->mBases[0]));
- memmove(s->mWords, &s->mWords[shift], (sizeof(s->mWords) / sizeof(s->mWords[0]) - shift) * sizeof(s->mWords[0]));
- memmove(s->mStarts, &s->mStarts[shift], (sizeof(s->mStarts) / sizeof(s->mStarts[0]) - shift) * sizeof(s->mStarts[0]));
+ s->shiftWords(shift);
s->mStartResult = s->mWords[0] - s->mStarts[0];
s->mWordCount -= shift;
// FIXME: need to adjust lineCount to account for discarded delimiters
@@ -1771,9 +1777,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
continue;
if (s->mWordCount == 0 && s->mContinuationNode)
return FOUND_NONE;
- s->mBases[s->mWordCount] = baseChars;
- s->mWords[s->mWordCount] = chars;
- s->mStarts[s->mWordCount] = s->mCurrentStart;
+ s->newWord(baseChars, chars);
s->mNumberWords |= 1 << s->mWordCount;
s->mUnparsed = true;
}
@@ -1796,9 +1800,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
case SECOND_HALF:
if (WTF::isASCIIAlpha(ch)) {
if (s->mLetterCount == 0) {
- s->mBases[s->mWordCount] = baseChars;
- s->mWords[s->mWordCount] = chars;
- s->mStarts[s->mWordCount] = s->mCurrentStart;
+ s->newWord(baseChars, chars);
s->mWordCount++;
}
s->mLetterCount++;
@@ -1917,9 +1919,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
s->mZipDelimiter = true;
else {
if (s->mLetterCount == 0) {
- s->mBases[s->mWordCount] = baseChars;
- s->mWords[s->mWordCount] = chars;
- s->mStarts[s->mWordCount] = s->mCurrentStart;
+ s->newWord(baseChars, chars);
s->mUnparsed = true;
}
++s->mLetterCount;
@@ -1990,7 +1990,8 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
goto nextTest;
abbr = true;
}
- letter = test[testIndex];
+ letter = &test[testIndex] < s->mEnds[wordsIndex] ?
+ test[testIndex] : ' ';
if (WTF::isASCIIAlpha(letter) == false && WTF::isASCIIDigit(letter) == false) {
if (s->mNumberWords != 0) {
int shift = 0;
@@ -2031,9 +2032,7 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
s->mNumberWords >>= ++shift;
if (s->mBases[0] != s->mBases[shift])
return FOUND_NONE;
- memmove(s->mBases, &s->mBases[shift], (sizeof(s->mBases) / sizeof(s->mBases[0]) - shift) * sizeof(s->mBases[0]));
- memmove(s->mWords, &s->mWords[shift], (sizeof(s->mWords) / sizeof(s->mWords[0]) - shift) * sizeof(s->mWords[0]));
- memmove(s->mStarts, &s->mStarts[shift], (sizeof(s->mStarts) / sizeof(s->mStarts[0]) - shift) * sizeof(s->mStarts[0]));
+ s->shiftWords(shift);
s->mStartResult = s->mWords[0] - s->mStarts[0];
s->mWordCount -= shift;
s->mProgress = ADDRESS_LINE;
@@ -2431,7 +2430,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node,
CachedNodeType* type, String* exported) const
{
Text* textNode = static_cast<Text*>(node);
- StringImpl* string = textNode->string();
+ StringImpl* string = textNode->dataImpl();
const UChar* baseChars = string->characters();
// const UChar* originalBase = baseChars;
int length = string->length();
@@ -2462,9 +2461,9 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node,
baseStart = start;
for (CachedNodeType checkType = ADDRESS_CACHEDNODETYPE;
checkType <= PHONE_CACHEDNODETYPE;
- checkType = (CachedNodeType) (checkType << 1))
+ checkType = static_cast<CachedNodeType>(checkType + 1))
{
- if ((checkType & mAllowableTypes) == 0)
+ if ((1 << (checkType - 1) & mAllowableTypes) == 0)
continue;
InlineTextBox* inlineTextBox = baseInline;
FindState findState;
@@ -2536,7 +2535,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node,
exported->truncate(0);
do {
Text* tempText = static_cast<Text*>(temp);
- StringImpl* string = tempText->string();
+ StringImpl* string = tempText->dataImpl();
int end = tempText == walk->mFinalNode ?
walk->mEnd : string->length();
exported->append(String(string->substring(
@@ -2596,7 +2595,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node,
} while (renderer == NULL);
baseInline = renderer->firstTextBox();
} while (baseInline == NULL);
- string = nextNode->string();
+ string = nextNode->dataImpl();
baseChars = string->characters();
inlineTextBox = baseInline;
start = inlineTextBox->start();
@@ -2606,7 +2605,7 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node,
tryNextCheckType:
node = textNode;
baseInline = saveInline;
- string = textNode->string();
+ string = textNode->dataImpl();
baseChars = string->characters();
}
if (foundBetter) {
@@ -2865,7 +2864,7 @@ bool CacheBuilder::ConstructTextRect(Text* textNode,
{
RenderText* renderText = (RenderText*) textNode->renderer();
EVisibility vis = renderText->style()->visibility();
- StringImpl* string = textNode->string();
+ StringImpl* string = textNode->dataImpl();
const UChar* chars = string->characters();
FloatPoint pt = renderText->localToAbsolute();
do {