diff options
16 files changed, 346 insertions, 264 deletions
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 7f4352b..9cb81e6 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -116,7 +116,6 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) : static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node())); } else m_contentLayer = new LayerAndroid(renderLayer); - m_dirtyRegion.setEmpty(); gDebugGraphicsLayerAndroidInstances++; } @@ -695,7 +694,7 @@ bool GraphicsLayerAndroid::repaint() PaintingPhase phase(this); // Paint the background into a separate context. phase.set(GraphicsLayerPaintBackground); - if (!paintContext(m_contentLayer, layerBounds)) + if (!paintContext(m_contentLayer, m_contentLayerContent)) return false; // Construct the foreground layer and draw. @@ -712,11 +711,17 @@ bool GraphicsLayerAndroid::repaint() // Paint everything else into the main recording canvas. phase.clear(GraphicsLayerPaintBackground); + // Invalidate the entire layer for now, as webkit will only send the + // setNeedsDisplayInRect() for the visible (clipped) scrollable area, + // offsetting the invals by the scroll position would not be enough. + // TODO: have webkit send us invals even for non visible area + m_foregroundLayerContent.invalidate(IntRect(0, 0, contentsRect.width(), contentsRect.height())); + // Paint at 0,0. IntSize scroll = layer->scrolledContentOffset(); layer->scrollToOffset(0, 0); // At this point, it doesn't matter if painting failed. - (void) paintContext(m_foregroundLayer, contentsRect); + (void) paintContext(m_foregroundLayer, m_foregroundLayerContent); layer->scrollToOffset(scroll.width(), scroll.height()); // Construct the clip layer for masking the contents. @@ -741,13 +746,8 @@ bool GraphicsLayerAndroid::repaint() // Set the scrollable bounds of the layer. setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer); - // Invalidate the entire layer for now, as webkit will only send the - // setNeedsDisplayInRect() for the visible (clipped) scrollable area, - // offsetting the invals by the scroll position would not be enough. - // TODO: have webkit send us invals even for non visible area - SkRegion region; - region.setRect(0, 0, contentsRect.width(), contentsRect.height()); - m_foregroundLayer->markAsDirty(region); + m_foregroundLayer->markAsDirty(m_foregroundLayerContent.dirtyRegion()); + m_foregroundLayerContent.dirtyRegion().setEmpty(); } else if (m_contentLayer->isFixedBackground()) { SkPicture* picture = new SkPicture(); SkCanvas* canvas = picture->beginRecording(layerBounds.width(), @@ -784,13 +784,13 @@ bool GraphicsLayerAndroid::repaint() GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer()); if (replicatedLayer->maskLayer()) { GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer()); - mask->paintContext(mask->m_contentLayer, layerBounds, false); + mask->paintContext(mask->m_contentLayer, m_contentLayerContent); } } // If there is no contents clip, we can draw everything into one // picture. - bool painting = paintContext(m_contentLayer, layerBounds); + bool painting = paintContext(m_contentLayer, m_contentLayerContent); if (!painting) return false; // Check for a scrollable iframe and report the scrolling @@ -811,8 +811,8 @@ bool GraphicsLayerAndroid::repaint() m_contentLayer->getSize().width(), m_contentLayer->getSize().height()); - m_contentLayer->markAsDirty(m_dirtyRegion); - m_dirtyRegion.setEmpty(); + m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion()); + m_contentLayerContent.dirtyRegion().setEmpty(); m_needsRepaint = false; return true; @@ -820,8 +820,8 @@ bool GraphicsLayerAndroid::repaint() if (m_needsRepaint && m_image && m_newImage) { // We need to tell the GL thread that we will need to repaint the // texture. Only do so if we effectively have a new image! - m_contentLayer->markAsDirty(m_dirtyRegion); - m_dirtyRegion.setEmpty(); + m_contentLayer->markAsDirty(m_contentLayerContent.dirtyRegion()); + m_contentLayerContent.dirtyRegion().setEmpty(); m_newImage = false; m_needsRepaint = false; return true; @@ -835,19 +835,14 @@ void GraphicsLayerAndroid::paintContents(GraphicsContext* gc, IntRect& dirty) } bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer, - const IntRect& rect, - bool checkOptimisations) + PicturePile& picture) { if (!layer) return false; TRACE_METHOD(); - // TODO: we might be able to reuse an existing picture instead of recreating it. - // we can't do that because of transparency -- for now, we just create - // a new picture every time. - WebCore::PicturePile picture; - picture.setSize(IntSize(rect.width(), rect.height())); + picture.setSize(IntSize(layer->getWidth(), layer->getHeight())); // TODO: add content checks (text, opacity, etc.) picture.updatePicturesIfNeeded(this); @@ -870,11 +865,9 @@ void GraphicsLayerAndroid::setNeedsDisplayInRect(const FloatRect& rect) return; } - SkRegion region; - region.setRect(rect.x(), rect.y(), - rect.x() + rect.width(), - rect.y() + rect.height()); - m_dirtyRegion.op(region, SkRegion::kUnion_Op); + m_contentLayerContent.invalidate(enclosingIntRect(rect)); + if (m_foregroundLayer) + m_foregroundLayerContent.invalidate(enclosingIntRect(rect)); m_needsRepaint = true; askForSync(); diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h index b40459d..28d4b09 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h @@ -154,9 +154,7 @@ private: bool repaint(); void needsNotifyClient(); - bool paintContext(LayerAndroid* layer, - const IntRect& rect, - bool checkOptimisations = true); + bool paintContext(LayerAndroid* layer, PicturePile& picture); bool m_needsSyncChildren; bool m_needsSyncMask; @@ -167,12 +165,13 @@ private: bool m_newImage; Image* m_image; - SkRegion m_dirtyRegion; - LayerAndroid* m_contentLayer; FixedBackgroundImageLayerAndroid* m_fixedBackgroundLayer; LayerAndroid* m_foregroundLayer; LayerAndroid* m_foregroundClipLayer; + + PicturePile m_contentLayerContent; + PicturePile m_foregroundLayerContent; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp index 464224a..c70a67d 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp @@ -43,7 +43,7 @@ #include "wtf/HashSet.h" #include "wtf/StringHasher.h" -#define NEW_OP(X) new (operationHeap()) GraphicsOperation::X +#define NEW_OP(X) new (heap()) GraphicsOperation::X #define USE_CLIPPING_PAINTER true @@ -133,7 +133,7 @@ public: ~CanvasState() { ALOGV("Delete %p", this); for (size_t i = 0; i < m_operations.size(); i++) - delete m_operations[i]; + m_operations[i]->~RecordingData(); m_operations.clear(); } @@ -202,15 +202,10 @@ private: // Careful, ordering matters here. Ordering is first constructed == last destroyed, // so we have to make sure our Heap is the first thing listed so that it is // the last thing destroyed. - LinearAllocator m_operationHeap; - LinearAllocator m_canvasStateHeap; - // Used by both PlatformGraphicsContext::State and SkPaint, as both are - // roughly the same size (72 bytes vs. 76 bytes, respectively) - LinearAllocator m_stateHeap; + LinearAllocator m_heap; public: RecordingImpl() - : m_canvasStateHeap(sizeof(CanvasState)) - , m_stateHeap(sizeof(SkPaint)) + : m_tree(&m_heap) , m_nodeCount(0) { } @@ -225,7 +220,7 @@ public: StateHashSet::iterator it = m_states.find(inState); if (it != m_states.end()) return (*it); - void* buf = m_stateHeap.alloc(sizeof(PlatformGraphicsContext::State)); + void* buf = heap()->alloc(sizeof(PlatformGraphicsContext::State)); PlatformGraphicsContext::State* state = new (buf) PlatformGraphicsContext::State(*inState); m_states.add(state); return state; @@ -235,7 +230,7 @@ public: SkPaintHashSet::iterator it = m_paints.find(&inPaint); if (it != m_paints.end()) return (*it); - void* buf = m_stateHeap.alloc(sizeof(SkPaint)); + void* buf = heap()->alloc(sizeof(SkPaint)); SkPaint* paint = new (buf) SkPaint(inPaint); m_paints.add(paint); return paint; @@ -284,12 +279,17 @@ public: toState->playback(context, fromId, toId); } - LinearAllocator* operationHeap() { return &m_operationHeap; } - LinearAllocator* canvasStateHeap() { return &m_canvasStateHeap; } + LinearAllocator* heap() { return &m_heap; } RTree::RTree m_tree; int m_nodeCount; + void dumpMemoryStats() { + static const char* PREFIX = " "; + ALOGD("Heap:"); + m_heap.dumpMemoryStats(PREFIX); + } + private: void clearStates() { @@ -495,12 +495,14 @@ PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(Recording* re mRecording->setRecording(new RecordingImpl()); mMatrixStack.append(SkMatrix::I()); mCurrentMatrix = &(mMatrixStack.last()); - pushStateOperation(new (canvasStateHeap()) CanvasState(0)); + pushStateOperation(new (heap()) CanvasState(0)); } PlatformGraphicsContextRecording::~PlatformGraphicsContextRecording() { ALOGV("RECORDING: end"); + IF_ALOGV() + mRecording->recording()->dumpMemoryStats(); } bool PlatformGraphicsContextRecording::isPaintingDisabled() @@ -521,7 +523,8 @@ SkCanvas* PlatformGraphicsContextRecording::recordingCanvas() void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity) { CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new (canvasStateHeap()) CanvasState(parent, opacity)); + pushStateOperation(new (heap()) CanvasState(parent, opacity)); + mRecordingStateStack.last().disableOpaqueTracking(); } void PlatformGraphicsContextRecording::endTransparencyLayer() @@ -533,7 +536,7 @@ void PlatformGraphicsContextRecording::save() { PlatformGraphicsContext::save(); CanvasState* parent = mRecordingStateStack.last().mCanvasState; - pushStateOperation(new (canvasStateHeap()) CanvasState(parent)); + pushStateOperation(new (heap()) CanvasState(parent)); pushMatrix(); } @@ -686,13 +689,13 @@ const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix() void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect, int thickness) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); appendStateOperation(NEW_OP(InnerRoundedRectClip)(rect, thickness)); } void PlatformGraphicsContextRecording::canvasClip(const Path& path) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); clip(path); } @@ -705,7 +708,7 @@ bool PlatformGraphicsContextRecording::clip(const FloatRect& rect) bool PlatformGraphicsContextRecording::clip(const Path& path) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); clipState(path.boundingRect()); appendStateOperation(NEW_OP(ClipPath)(path)); return true; @@ -720,21 +723,21 @@ bool PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints, bool PlatformGraphicsContextRecording::clipOut(const IntRect& r) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); appendStateOperation(NEW_OP(ClipOut)(r)); return true; } bool PlatformGraphicsContextRecording::clipOut(const Path& path) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); appendStateOperation(NEW_OP(ClipPath)(path, true)); return true; } bool PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule) { - mRecordingStateStack.last().setHasComplexClip(); + mRecordingStateStack.last().disableOpaqueTracking(); clipState(pathToClip.boundingRect()); GraphicsOperation::ClipPath* operation = NEW_OP(ClipPath)(pathToClip); operation->setWindRule(clipRule); @@ -900,9 +903,9 @@ void PlatformGraphicsContextRecording::drawPosText(const void* inText, size_t by } FloatRect bounds = approximateTextBounds(byteLength / sizeof(uint16_t), inPos, inPaint); const SkPaint* paint = mRecording->recording()->getSkPaint(inPaint); - int posSize = sizeof(SkPoint) * paint->countText(inText, byteLength); - void* text = operationHeap()->alloc(posSize + byteLength); - SkPoint* pos = (SkPoint*) ((char*)text + byteLength); + size_t posSize = sizeof(SkPoint) * paint->countText(inText, byteLength); + void* text = heap()->alloc(byteLength); + SkPoint* pos = (SkPoint*) heap()->alloc(posSize); memcpy(text, inText, byteLength); memcpy(pos, inPos, posSize); appendDrawingOperation(NEW_OP(DrawPosText)(text, byteLength, pos, paint), bounds); @@ -928,7 +931,9 @@ void PlatformGraphicsContextRecording::clipState(const FloatRect& clip) void PlatformGraphicsContextRecording::pushStateOperation(CanvasState* canvasState) { ALOGV("RECORDING: pushStateOperation: %p(isLayer=%d)", canvasState, canvasState->isTransparencyLayer()); - mRecordingStateStack.append(canvasState); + + RecordingState* parent = mRecordingStateStack.isEmpty() ? 0 : &(mRecordingStateStack.last()); + mRecordingStateStack.append(RecordingState(canvasState, parent)); mRecording->recording()->addCanvasState(canvasState); } @@ -942,7 +947,7 @@ void PlatformGraphicsContextRecording::popStateOperation() state.mCanvasState, state.mCanvasState->isTransparencyLayer()); mRecording->recording()->removeCanvasState(state.mCanvasState); state.mCanvasState->~CanvasState(); - canvasStateHeap()->rewindTo(state.mCanvasState); + heap()->rewindIfLastAlloc(state.mCanvasState, sizeof(CanvasState)); } else { ALOGV("RECORDING: popStateOperation: %p(isLayer=%d)", state.mCanvasState, state.mCanvasState->isTransparencyLayer()); @@ -998,6 +1003,13 @@ IntRect PlatformGraphicsContextRecording::calculateFinalBounds(FloatRect bounds) IntRect PlatformGraphicsContextRecording::calculateCoveredBounds(FloatRect bounds) { + if (mRecordingStateStack.last().mOpaqueTrackingDisabled + || m_state->alpha != 1.0f + || (m_state->mode != SkXfermode::kSrc_Mode && m_state->mode != SkXfermode::kSrcOver_Mode) + || !mCurrentMatrix->rectStaysRect()) { + return IntRect(); + } + SkRect translated; mCurrentMatrix->mapRect(&translated, bounds); FloatRect ftrect = translated; @@ -1025,38 +1037,28 @@ void PlatformGraphicsContextRecording::appendDrawingOperation( if (ibounds.isEmpty()) { ALOGV("RECORDING: Operation %s() was clipped out", operation->name()); operation->~Operation(); - operationHeap()->rewindTo(operation); return; } - if (operation->isOpaque() - && !untranslatedBounds.isEmpty() - && operation->m_state->alpha == 1.0f - && mCurrentMatrix->rectStaysRect() - && !state.mHasComplexClip) { + if (operation->isOpaque() && !untranslatedBounds.isEmpty()) { // if the operation maps to an opaque rect, record the area it will cover operation->setOpaqueRect(calculateCoveredBounds(untranslatedBounds)); } ALOGV("RECORDING: appendOperation %p->%s() bounds " INT_RECT_FORMAT, operation, operation->name(), INT_RECT_ARGS(ibounds)); - RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); + RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++); mRecording->recording()->m_tree.insert(ibounds, data); } void PlatformGraphicsContextRecording::appendStateOperation(GraphicsOperation::Operation* operation) { ALOGV("RECORDING: appendOperation %p->%s()", operation, operation->name()); - RecordingData* data = new RecordingData(operation, mRecording->recording()->m_nodeCount++); + RecordingData* data = new (heap()) RecordingData(operation, mRecording->recording()->m_nodeCount++); mRecordingStateStack.last().mCanvasState->adoptAndAppend(data); } -LinearAllocator* PlatformGraphicsContextRecording::operationHeap() -{ - return mRecording->recording()->operationHeap(); -} - -LinearAllocator* PlatformGraphicsContextRecording::canvasStateHeap() +LinearAllocator* PlatformGraphicsContextRecording::heap() { - return mRecording->recording()->canvasStateHeap(); + return mRecording->recording()->heap(); } } // WebCore diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h index d62eb8a..061ee0e 100644 --- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h +++ b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h @@ -160,8 +160,7 @@ private: void popMatrix(); IntRect calculateFinalBounds(FloatRect bounds); IntRect calculateCoveredBounds(FloatRect bounds); - LinearAllocator* operationHeap(); - LinearAllocator* canvasStateHeap(); + LinearAllocator* heap(); SkPicture* mPicture; SkMatrix* mCurrentMatrix; @@ -169,22 +168,23 @@ private: Recording* mRecording; class RecordingState { public: - RecordingState(CanvasState* state) + RecordingState(CanvasState* state, const RecordingState* parent) : mCanvasState(state) , mHasDrawing(false) - , mHasClip(false) - , mHasComplexClip(false) + , mHasClip(parent ? parent->mHasClip : false) + , mOpaqueTrackingDisabled(parent ? parent->mOpaqueTrackingDisabled : false) + , mBounds(parent ? parent->mBounds : FloatRect()) {} RecordingState(const RecordingState& other) : mCanvasState(other.mCanvasState) , mHasDrawing(other.mHasDrawing) , mHasClip(other.mHasClip) - , mHasComplexClip(false) + , mOpaqueTrackingDisabled(other.mOpaqueTrackingDisabled) , mBounds(other.mBounds) {} - void setHasComplexClip() { mHasComplexClip = true; } + void disableOpaqueTracking() { mOpaqueTrackingDisabled = true; } void clip(const FloatRect& rect) { @@ -199,7 +199,7 @@ private: CanvasState* mCanvasState; bool mHasDrawing; bool mHasClip; - bool mHasComplexClip; + bool mOpaqueTrackingDisabled; FloatRect mBounds; }; Vector<RecordingState> mRecordingStateStack; diff --git a/Source/WebCore/platform/graphics/android/context/RTree.cpp b/Source/WebCore/platform/graphics/android/context/RTree.cpp index fa048b7..2e24c34 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.cpp +++ b/Source/WebCore/platform/graphics/android/context/RTree.cpp @@ -33,6 +33,15 @@ #include "AndroidLog.h" #include "LinearAllocator.h" +namespace WebCore { + +void* RecordingData::operator new(size_t size, LinearAllocator* allocator) +{ + return allocator->alloc(size); +} + +} + namespace RTree { #ifdef DEBUG @@ -123,12 +132,12 @@ int computeDeltaArea(Node* node, int& minx, int& miny, // ////////////////////////////////////////////////////////////////////// -RTree::RTree(int M) +RTree::RTree(WebCore::LinearAllocator* allocator, int M) + : m_allocator(allocator) { m_maxChildren = M; m_listA = new ElementList(M); m_listB = new ElementList(M); - m_allocator = new WebCore::LinearAllocator(sizeof(Node)); m_root = Node::create(this); } @@ -137,7 +146,6 @@ RTree::~RTree() delete m_listA; delete m_listB; deleteNode(m_root); - delete m_allocator; } void RTree::insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload) @@ -263,7 +271,8 @@ Node::~Node() for (unsigned i = 0; i < m_nbChildren; i++) m_tree->deleteNode(m_children[i]); delete[] m_children; - delete m_payload; + if (m_payload) + m_payload->~RecordingData(); } void Node::setParent(Node* node) diff --git a/Source/WebCore/platform/graphics/android/context/RTree.h b/Source/WebCore/platform/graphics/android/context/RTree.h index 366e3d1..50962ef 100644 --- a/Source/WebCore/platform/graphics/android/context/RTree.h +++ b/Source/WebCore/platform/graphics/android/context/RTree.h @@ -46,6 +46,12 @@ public: size_t m_orderBy; GraphicsOperation::Operation* m_operation; + + void* operator new(size_t size, LinearAllocator* allocator); + + // Purposely not implemented - use a LinearAllocator please + void* operator new(size_t size); + void operator delete(void* ptr); }; } // namespace WebCore @@ -58,7 +64,7 @@ class Node; class RTree { public: // M -- max number of children per node - RTree(int M = 10); + RTree(WebCore::LinearAllocator* allocator, int M = 10); ~RTree(); void insert(WebCore::IntRect& bounds, WebCore::RecordingData* payload); diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h index 02a0cea..afae949 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h @@ -33,12 +33,13 @@ #include "FontOrientation.h" #include "TextOrientation.h" #include <wtf/text/StringImpl.h> +#include "SkLanguage.h" +#include "SkPaint.h" #ifndef NDEBUG #include "PlatformString.h" #endif -class SkPaint; class SkTypeface; struct HB_FaceRec_; @@ -62,13 +63,13 @@ public: ~FontPlatformData(); FontPlatformData(WTF::HashTableDeletedValueType) - : mTypeface(hashTableDeletedFontValue()) { } + : m_typeface(hashTableDeletedFontValue()) { } bool isHashTableDeletedValue() const { - return mTypeface == hashTableDeletedFontValue(); + return m_typeface == hashTableDeletedFontValue(); } - FontOrientation orientation() const { return mOrientation; } - void setOrientation(FontOrientation orientation) { mOrientation = orientation; } + FontOrientation orientation() const { return m_orientation; } + void setOrientation(FontOrientation orientation) { m_orientation = orientation; } FontPlatformData& operator=(const FontPlatformData&); bool operator==(const FontPlatformData& a) const; @@ -80,7 +81,7 @@ public: // ------------------------------------------------------------------------- uint32_t uniqueID() const; - float size() const { return mTextSize; } + float size() const { return m_textSize; } unsigned hash() const; int emSizeInFontUnits() const; bool isFixedPitch() const; @@ -90,10 +91,12 @@ public: #endif HB_FaceRec_* harfbuzzFace() const; - SkTypeface* typeface() const { return mTypeface; } + SkTypeface* typeface() const { return m_typeface; } - bool isFakeBold() const { return mFakeBold; } - bool isFakeItalic() const { return mFakeItalic; } + bool isFakeBold() const { return m_fakeBold; } + bool isFakeItalic() const { return m_fakeItalic; } + + static void setDefaultLanguage(const char* language); private: class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> { @@ -115,14 +118,15 @@ private: HB_FaceRec_* m_harfbuzzFace; }; - SkTypeface* mTypeface; - float mTextSize; - mutable int mEmSizeInFontUnits; - bool mFakeBold; - bool mFakeItalic; - FontOrientation mOrientation; - TextOrientation mTextOrientation; + SkTypeface* m_typeface; + float m_textSize; + mutable int m_emSizeInFontUnits; + bool m_fakeBold; + bool m_fakeItalic; + FontOrientation m_orientation; + TextOrientation m_textOrientation; mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace; + static SkLanguage s_defaultLanguage; static SkTypeface* hashTableDeletedFontValue() { return reinterpret_cast<SkTypeface*>(-1); diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp index fc254c0..f3e4227 100644 --- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp @@ -41,26 +41,26 @@ //#define COUNT_FONTPLATFORMDATA_LIFE #ifdef COUNT_FONTPLATFORMDATA_LIFE -static int gCount; -static int gMaxCount; +static int g_count; +static int g_maxCount; static void inc_count() { - if (++gCount > gMaxCount) + if (++g_count > g_maxCount) { - gMaxCount = gCount; - SkDebugf("---------- FontPlatformData %d\n", gMaxCount); + g_maxCount = g_count; + SkDebugf("---------- FontPlatformData %d\n", g_maxCount); } } -static void dec_count() { --gCount; } +static void dec_count() { --g_count; } #else #define inc_count() #define dec_count() #endif #ifdef TRACE_FONTPLATFORMDATA_LIFE - #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic) + #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, m_typeface, m_textSize, m_fakeBold, m_fakeItalic) #else #define trace(num) #endif @@ -75,8 +75,8 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() } FontPlatformData::FontPlatformData() - : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), - mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) + : m_typeface(NULL), m_textSize(0), m_emSizeInFontUnits(0), m_fakeBold(false), m_fakeItalic(false), + m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight) { inc_count(); trace(1); @@ -84,30 +84,29 @@ FontPlatformData::FontPlatformData() FontPlatformData::FontPlatformData(const FontPlatformData& src) { - if (hashTableDeletedFontValue() != src.mTypeface) { - SkSafeRef(src.mTypeface); + if (hashTableDeletedFontValue() != src.m_typeface) { + SkSafeRef(src.m_typeface); } - mTypeface = src.mTypeface; - mTextSize = src.mTextSize; - mEmSizeInFontUnits = src.mEmSizeInFontUnits; - mFakeBold = src.mFakeBold; - mFakeItalic = src.mFakeItalic; + m_typeface = src.m_typeface; + m_textSize = src.m_textSize; + m_emSizeInFontUnits = src.m_emSizeInFontUnits; + m_fakeBold = src.m_fakeBold; + m_fakeItalic = src.m_fakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; - + m_orientation = src.m_orientation; + m_textOrientation = src.m_textOrientation; inc_count(); trace(2); } FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) - : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), - mOrientation(orientation), mTextOrientation(textOrientation) + : m_typeface(tf), m_textSize(textSize), m_emSizeInFontUnits(0), m_fakeBold(fakeBold), m_fakeItalic(fakeItalic), + m_orientation(orientation), m_textOrientation(textOrientation) { - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); + if (hashTableDeletedFontValue() != m_typeface) { + SkSafeRef(m_typeface); } inc_count(); @@ -115,11 +114,11 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold } FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) - : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), - mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace) + : m_typeface(src.m_typeface), m_textSize(textSize), m_emSizeInFontUnits(src.m_emSizeInFontUnits), m_fakeBold(src.m_fakeBold), m_fakeItalic(src.m_fakeItalic), + m_orientation(src.m_orientation), m_textOrientation(src.m_textOrientation), m_harfbuzzFace(src.m_harfbuzzFace) { - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); + if (hashTableDeletedFontValue() != m_typeface) { + SkSafeRef(m_typeface); } inc_count(); @@ -127,20 +126,20 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) } FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) - : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), - mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) + : m_typeface(NULL), m_textSize(size), m_emSizeInFontUnits(0), m_fakeBold(bold), m_fakeItalic(oblique), + m_orientation(Horizontal), m_textOrientation(TextOrientationVerticalRight) { inc_count(); trace(5); } FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) - : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), - mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), - mTextOrientation(src.mTextOrientation) + : m_typeface(tf), m_textSize(src.m_textSize), m_emSizeInFontUnits(0), m_fakeBold(src.m_fakeBold), + m_fakeItalic(src.m_fakeItalic), m_orientation(src.m_orientation), + m_textOrientation(src.m_textOrientation) { - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeRef(mTypeface); + if (hashTableDeletedFontValue() != m_typeface) { + SkSafeRef(m_typeface); } inc_count(); @@ -154,61 +153,67 @@ FontPlatformData::~FontPlatformData() SkDebugf("----------- ~FontPlatformData\n"); #endif - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeUnref(mTypeface); + if (hashTableDeletedFontValue() != m_typeface) { + SkSafeUnref(m_typeface); } } int FontPlatformData::emSizeInFontUnits() const { - if (mEmSizeInFontUnits) - return mEmSizeInFontUnits; + if (m_emSizeInFontUnits) + return m_emSizeInFontUnits; SkAdvancedTypefaceMetrics* metrics = 0; - if (mTypeface) - metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); + if (m_typeface) + metrics = m_typeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); if (metrics) { - mEmSizeInFontUnits = metrics->fEmSize; + m_emSizeInFontUnits = metrics->fEmSize; metrics->unref(); } else - mEmSizeInFontUnits = 1000; // default value copied from Skia. - return mEmSizeInFontUnits; + m_emSizeInFontUnits = 1000; // default value copied from Skia. + return m_emSizeInFontUnits; } FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) { - if (hashTableDeletedFontValue() != src.mTypeface) { - SkSafeRef(src.mTypeface); + if (hashTableDeletedFontValue() != src.m_typeface) { + SkSafeRef(src.m_typeface); } - if (hashTableDeletedFontValue() != mTypeface) { - SkSafeUnref(mTypeface); + if (hashTableDeletedFontValue() != m_typeface) { + SkSafeUnref(m_typeface); } - mTypeface = src.mTypeface; - mEmSizeInFontUnits = src.mEmSizeInFontUnits; - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; - mFakeItalic = src.mFakeItalic; + m_typeface = src.m_typeface; + m_emSizeInFontUnits = src.m_emSizeInFontUnits; + m_textSize = src.m_textSize; + m_fakeBold = src.m_fakeBold; + m_fakeItalic = src.m_fakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; + m_orientation = src.m_orientation; + m_textOrientation = src.m_textOrientation; return *this; } +SkLanguage FontPlatformData::s_defaultLanguage; +void FontPlatformData::setDefaultLanguage(const char* language) { + s_defaultLanguage = SkLanguage(language); +} + void FontPlatformData::setupPaint(SkPaint* paint) const { - if (hashTableDeletedFontValue() == mTypeface) + if (hashTableDeletedFontValue() == m_typeface) paint->setTypeface(0); else - paint->setTypeface(mTypeface); + paint->setTypeface(m_typeface); paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); - paint->setTextSize(SkFloatToScalar(mTextSize)); - paint->setFakeBoldText(mFakeBold); - paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); + paint->setTextSize(SkFloatToScalar(m_textSize)); + paint->setFakeBoldText(m_fakeBold); + paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1/4 : 0); + paint->setLanguage(s_defaultLanguage); #ifndef SUPPORT_COMPLEX_SCRIPTS paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); #endif @@ -216,44 +221,44 @@ void FontPlatformData::setupPaint(SkPaint* paint) const uint32_t FontPlatformData::uniqueID() const { - if (hashTableDeletedFontValue() == mTypeface) + if (hashTableDeletedFontValue() == m_typeface) return SkTypeface::UniqueID(0); else - return SkTypeface::UniqueID(mTypeface); + return SkTypeface::UniqueID(m_typeface); } bool FontPlatformData::operator==(const FontPlatformData& a) const { - return mTypeface == a.mTypeface && - mTextSize == a.mTextSize && - mFakeBold == a.mFakeBold && - mFakeItalic == a.mFakeItalic && - mOrientation == a.mOrientation && - mTextOrientation == a.mTextOrientation; + return m_typeface == a.m_typeface && + m_textSize == a.m_textSize && + m_fakeBold == a.m_fakeBold && + m_fakeItalic == a.m_fakeItalic && + m_orientation == a.m_orientation && + m_textOrientation == a.m_textOrientation; } unsigned FontPlatformData::hash() const { unsigned h; - if (hashTableDeletedFontValue() == mTypeface) { - h = reinterpret_cast<unsigned>(mTypeface); + if (hashTableDeletedFontValue() == m_typeface) { + h = reinterpret_cast<unsigned>(m_typeface); } else { - h = SkTypeface::UniqueID(mTypeface); + h = SkTypeface::UniqueID(m_typeface); } - uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&mTextSize); + uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&m_textSize); - h ^= 0x01010101 * ((static_cast<int>(mTextOrientation) << 3) | (static_cast<int>(mOrientation) << 2) | - ((int)mFakeBold << 1) | (int)mFakeItalic); + h ^= 0x01010101 * ((static_cast<int>(m_textOrientation) << 3) | (static_cast<int>(m_orientation) << 2) | + ((int)m_fakeBold << 1) | (int)m_fakeItalic); h ^= sizeAsInt; return h; } bool FontPlatformData::isFixedPitch() const { - if (mTypeface && (mTypeface != hashTableDeletedFontValue())) - return mTypeface->isFixedWidth(); + if (m_typeface && (m_typeface != hashTableDeletedFontValue())) + return m_typeface->isFixedWidth(); else return false; } diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index 67d1259..84ce910 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -803,13 +803,14 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle st r.set(m_clippingRect.x(), m_clippingRect.y(), m_clippingRect.x() + m_clippingRect.width(), m_clippingRect.y() + m_clippingRect.height()); - canvas->clipRect(r); - SkMatrix matrix; - GLUtils::toSkMatrix(matrix, m_drawTransform); - SkMatrix canvasMatrix = canvas->getTotalMatrix(); - matrix.postConcat(canvasMatrix); - canvas->setMatrix(matrix); - onDraw(canvas, m_drawOpacity, 0, style); + if (canvas->clipRect(r)) { + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + matrix.postConcat(canvasMatrix); + canvas->setMatrix(matrix); + onDraw(canvas, m_drawOpacity, 0, style); + } } if (!drawChildren) diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp index e584b81..aa18898 100644 --- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp @@ -57,7 +57,7 @@ // number to cap the layer tile texturs, it worked on both phones and tablets. // TODO: after merge the pool of base tiles and layer tiles, we should revisit // the logic of allocation management. -#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4) +#define MAX_TEXTURE_ALLOCATION ((10+TILE_PREFETCH_DISTANCE*2)*(7+TILE_PREFETCH_DISTANCE*2)*4) #define TILE_WIDTH 256 #define TILE_HEIGHT 256 @@ -105,10 +105,10 @@ TilesManager::TilesManager() , m_eglContext(EGL_NO_CONTEXT) { ALOGV("TilesManager ctor"); - m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); - m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION); + m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2); + m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2); + m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2); + m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION / 2); m_textureGenerators = new sp<TexturesGenerator>[NUM_TEXTURES_GENERATORS]; for (int i = 0; i < NUM_TEXTURES_GENERATORS; i++) { diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp index 8aa1616..b945944 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.cpp @@ -33,17 +33,16 @@ namespace WebCore { -// The ideal size of a page allocation -#define TARGET_PAGE_SIZE 16384 // 16kb - -// our pool needs to big enough to hold at least this many items -#define MIN_OBJECT_COUNT 4 +// The ideal size of a page allocation (these need to be multiples of 4) +#define INITIAL_PAGE_SIZE ((size_t)4096) // 4kb +#define MAX_PAGE_SIZE ((size_t)131072) // 128kb // The maximum amount of wasted space we can have per page // Allocations exceeding this will have their own dedicated page // If this is too low, we will malloc too much // Too high, and we may waste too much space -#define MAX_WASTE_SIZE ((size_t)256) +// Must be smaller than INITIAL_PAGE_SIZE +#define MAX_WASTE_SIZE ((size_t)1024) #define ALIGN(x) (x + (x % sizeof(int))) @@ -98,21 +97,17 @@ private: Page* m_nextPage; }; -LinearAllocator::LinearAllocator(size_t averageAllocSize) - : m_next(0) +LinearAllocator::LinearAllocator() + : m_pageSize(INITIAL_PAGE_SIZE) + , m_maxAllocSize(MAX_WASTE_SIZE) + , m_next(0) , m_currentPage(0) , m_pages(0) + , m_totalAllocated(0) + , m_wastedSpace(0) + , m_pageCount(0) + , m_dedicatedPageCount(0) { - if (averageAllocSize) { - int usable_page_size = TARGET_PAGE_SIZE - sizeof(LinearAllocator::Page); - int pcount = usable_page_size / averageAllocSize; - if (pcount < MIN_OBJECT_COUNT) - pcount = MIN_OBJECT_COUNT; - m_pageSize = pcount * averageAllocSize + sizeof(LinearAllocator::Page); - } else - m_pageSize = TARGET_PAGE_SIZE; - m_pageSize = ALIGN(m_pageSize); - m_maxAllocSize = std::min(MAX_WASTE_SIZE, (m_pageSize - sizeof(LinearAllocator::Page))); } LinearAllocator::~LinearAllocator(void) @@ -136,11 +131,21 @@ void* LinearAllocator::end(Page* p) return ((char*)p) + m_pageSize; } +bool LinearAllocator::fitsInCurrentPage(size_t size) +{ + return m_next && ((char*)m_next + size) <= end(m_currentPage); +} + void LinearAllocator::ensureNext(size_t size) { - if (m_next && ((char*)m_next + size) <= end(m_currentPage)) + if (fitsInCurrentPage(size)) return; - Page* p = newPage(); + if (m_currentPage && m_pageSize < MAX_PAGE_SIZE) { + m_pageSize = std::min(MAX_PAGE_SIZE, m_pageSize * 2); + m_pageSize = ALIGN(m_pageSize); + } + m_wastedSpace += m_pageSize; + Page* p = newPage(m_pageSize); if (m_currentPage) m_currentPage->setNext(p); m_currentPage = p; @@ -149,25 +154,14 @@ void LinearAllocator::ensureNext(size_t size) m_next = start(m_currentPage); } -unsigned LinearAllocator::memusage() -{ - unsigned memusage = 0; - Page* p = m_pages; - while (p) { - memusage += m_pageSize; - p = p->next(); - } - return memusage; -} - void* LinearAllocator::alloc(size_t size) { size = ALIGN(size); - if (size > m_maxAllocSize) { + if (size > m_maxAllocSize && !fitsInCurrentPage(size)) { + ALOGV("Exceeded max size %d > %d", size, m_maxAllocSize); // Allocation is too large, create a dedicated page for the allocation - ADD_ALLOCATION(size); - void* buf = malloc(size + sizeof(LinearAllocator::Page)); - Page* page = new (buf) Page(); + Page* page = newPage(size); + m_dedicatedPageCount++; page->setNext(m_pages); m_pages = page; if (!m_currentPage) @@ -177,21 +171,55 @@ void* LinearAllocator::alloc(size_t size) ensureNext(size); void* ptr = m_next; m_next = ((char*)m_next) + size; + m_wastedSpace -= size; return ptr; } -void LinearAllocator::rewindTo(void* ptr) +void LinearAllocator::rewindIfLastAlloc(void* ptr, size_t allocSize) { // Don't bother rewinding across pages - if (ptr >= start(m_currentPage) && ptr < end(m_currentPage)) + if (ptr >= start(m_currentPage) && ptr < end(m_currentPage) + && ptr == ((char*)m_next - allocSize)) { + m_totalAllocated -= allocSize; + m_wastedSpace += allocSize; m_next = ptr; + } } -LinearAllocator::Page* LinearAllocator::newPage() +LinearAllocator::Page* LinearAllocator::newPage(size_t pageSize) { - ADD_ALLOCATION(m_pageSize); - void* buf = malloc(m_pageSize); + pageSize += sizeof(LinearAllocator::Page); + ADD_ALLOCATION(pageSize); + m_totalAllocated += pageSize; + m_pageCount++; + void* buf = malloc(pageSize); return new (buf) Page(); } +static const char* toSize(size_t value, float& result) +{ + if (value < 2000) { + result = value; + return "B"; + } + if (value < 2000000) { + result = value / 1024.0f; + return "KB"; + } + result = value / 1048576.0f; + return "MB"; +} + +void LinearAllocator::dumpMemoryStats(const char* prefix) +{ + float prettySize; + const char* prettySuffix; + prettySuffix = toSize(m_totalAllocated, prettySize); + ALOGD("%sTotal allocated: %.2f%s", prefix, prettySize, prettySuffix); + prettySuffix = toSize(m_wastedSpace, prettySize); + ALOGD("%sWasted space: %.2f%s (%.1f%%)", prefix, prettySize, prettySuffix, + (float) m_wastedSpace / (float) m_totalAllocated * 100.0f); + ALOGD("%sPages %d (dedicated %d)", prefix, m_pageCount, m_dedicatedPageCount); +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h index 1f3265c..8cabf7c 100644 --- a/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h +++ b/Source/WebCore/platform/graphics/android/utils/LinearAllocator.h @@ -31,29 +31,36 @@ namespace WebCore { class LinearAllocator { public: - LinearAllocator(size_t averageAllocSize = 0); + LinearAllocator(); ~LinearAllocator(); void* alloc(size_t size); - void rewindTo(void*); + void rewindIfLastAlloc(void* ptr, size_t allocSize); + + void dumpMemoryStats(const char* prefix = ""); private: LinearAllocator(const LinearAllocator& other); class Page; - Page* newPage(); + Page* newPage(size_t pageSize); + bool fitsInCurrentPage(size_t size); void ensureNext(size_t size); void* start(Page *p); void* end(Page* p); - unsigned memusage(); - size_t m_pageSize; size_t m_maxAllocSize; void* m_next; Page* m_currentPage; Page* m_pages; + + // Memory usage tracking + size_t m_totalAllocated; + size_t m_wastedSpace; + size_t m_pageCount; + size_t m_dedicatedPageCount; }; } // namespace WebCore diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp index 91f3e74..f995e92 100644 --- a/Source/WebKit/android/jni/PicturePile.cpp +++ b/Source/WebKit/android/jni/PicturePile.cpp @@ -55,16 +55,6 @@ static SkIRect toSkIRect(const IntRect& rect) { return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); } -static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) { - SkRect clip; - if (!canvas->getClipBounds(&clip)) { - ALOGW("Empty clip!"); - return IntRect(); - } - clip.intersect(0, 0, size.width(), size.height()); - return enclosingIntRect(clip); -} - PictureContainer::PictureContainer(const PictureContainer& other) : picture(other.picture) , area(other.area) @@ -94,11 +84,10 @@ void PicturePile::draw(SkCanvas* canvas) * the rect bounds of the SkRegion for the clip, so this still can't be * used for translucent surfaces */ - IntRect clipBounds = extractClipBounds(canvas, m_size); - if (clipBounds.isEmpty()) + if (canvas->quickReject(SkRect::MakeWH(m_size.width(), m_size.height()), + SkCanvas::kBW_EdgeType)) return; - SkRegion clipRegion(toSkIRect(clipBounds)); - drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1); + drawWithClipRecursive(canvas, m_pile.size() - 1); } void PicturePile::clearPrerenders() @@ -107,24 +96,23 @@ void PicturePile::clearPrerenders() m_pile[i].prerendered.clear(); } -void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, - int index) +void PicturePile::drawWithClipRecursive(SkCanvas* canvas, int index) { // TODO: Add some debug visualizations of this - if (index < 0 || clipRegion.isEmpty()) + if (index < 0) return; PictureContainer& pc = m_pile[index]; - IntRect intersection = clipRegion.getBounds(); - intersection.intersect(pc.area); - if (pc.picture && !intersection.isEmpty()) { - clipRegion.op(intersection, SkRegion::kDifference_Op); - drawWithClipRecursive(canvas, clipRegion, index - 1); - int saved = canvas->save(); - if (canvas->clipRect(intersection)) + if (pc.picture && !canvas->quickReject(pc.area, SkCanvas::kBW_EdgeType)) { + int saved = canvas->save(SkCanvas::kClip_SaveFlag); + if (canvas->clipRect(pc.area, SkRegion::kDifference_Op)) + drawWithClipRecursive(canvas, index - 1); + canvas->restoreToCount(saved); + saved = canvas->save(SkCanvas::kClip_SaveFlag); + if (canvas->clipRect(pc.area)) drawPicture(canvas, pc); canvas->restoreToCount(saved); } else - drawWithClipRecursive(canvas, clipRegion, index - 1); + drawWithClipRecursive(canvas, index - 1); } // Used by WebViewCore diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h index 6e3e46d..1f99054 100644 --- a/Source/WebKit/android/jni/PicturePile.h +++ b/Source/WebKit/android/jni/PicturePile.h @@ -113,7 +113,7 @@ private: void updatePicture(PicturePainter* painter, PictureContainer& container); Picture* recordPicture(PicturePainter* painter, PictureContainer& container); void appendToPile(const IntRect& inval, const IntRect& originalInval = IntRect()); - void drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, int index); + void drawWithClipRecursive(SkCanvas* canvas, int index); void drawPicture(SkCanvas* canvas, PictureContainer& pc); IntSize m_size; diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index fd5e9c4..920119b 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -134,6 +134,7 @@ #include "autofill/WebAutofill.h" #include "htmlediting.h" #include "markup.h" +#include "unicode/uloc.h" #include "visible_units.h" #include <JNIHelp.h> @@ -4407,6 +4408,44 @@ void WebViewCore::getLocale(String& language, String& region) region = String(propRegn, 2); } +// generate bcp47 identifier for the supplied language/region +static void toLanguageTag(char* output, size_t outSize, const String& language, + const String& region) { + if (output == NULL || outSize <= 0) + return; + String locale = language; + locale.append('_'); + locale.append(region); + char canonicalChars[ULOC_FULLNAME_CAPACITY]; + UErrorCode uErr = U_ZERO_ERROR; + uloc_canonicalize(locale.ascii().data(), canonicalChars, + ULOC_FULLNAME_CAPACITY, &uErr); + if (U_SUCCESS(uErr)) { + char likelyChars[ULOC_FULLNAME_CAPACITY]; + uErr = U_ZERO_ERROR; + uloc_addLikelySubtags(canonicalChars, likelyChars, + ULOC_FULLNAME_CAPACITY, &uErr); + if (U_SUCCESS(uErr)) { + uErr = U_ZERO_ERROR; + uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr); + if (U_SUCCESS(uErr)) { + return; + } else { + ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars, + u_errorName(uErr)); + } + } else { + ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", canonicalChars, + u_errorName(uErr)); + } + } else { + ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale.ascii().data(), + u_errorName(uErr)); + } + // unable to build a proper language identifier + output[0] = '\0'; +} + void WebViewCore::updateLocale() { static String prevLang; @@ -4421,6 +4460,9 @@ void WebViewCore::updateLocale() prevRegn = region; GlyphPageTreeNode::resetRoots(); fontCache()->invalidate(); + char langTag[ULOC_FULLNAME_CAPACITY]; + toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, language, region); + FontPlatformData::setDefaultLanguage(langTag); } } diff --git a/Tools/android/webkitmerge/Android.mk b/Tools/android/webkitmerge/Android.mk index 2ff1538..19f1cde 100644 --- a/Tools/android/webkitmerge/Android.mk +++ b/Tools/android/webkitmerge/Android.mk @@ -19,6 +19,4 @@ LOCAL_SRC_FILES := webkitmerge.cpp LOCAL_MODULE := webkitmerge -LOCAL_MODULE_TAGS := eng - include $(BUILD_HOST_EXECUTABLE) |