summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--WebCore/Android.mk2
-rw-r--r--WebCore/platform/android/RenderThemeAndroid.cpp20
-rw-r--r--WebCore/platform/graphics/android/BaseLayerAndroid.cpp14
-rw-r--r--WebCore/platform/graphics/android/BaseTile.cpp20
-rw-r--r--WebCore/platform/graphics/android/BaseTile.h5
-rw-r--r--WebCore/platform/graphics/android/FontAndroid.cpp5
-rw-r--r--WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp16
-rw-r--r--WebCore/platform/graphics/android/GraphicsContextAndroid.cpp13
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp2
-rw-r--r--WebCore/platform/graphics/android/PaintTileOperation.cpp (renamed from WebCore/platform/graphics/android/TileSet.cpp)86
-rw-r--r--WebCore/platform/graphics/android/PaintTileOperation.h (renamed from WebCore/platform/graphics/android/PaintTileSetOperation.h)30
-rw-r--r--WebCore/platform/graphics/android/PlatformGraphicsContext.h7
-rw-r--r--WebCore/platform/graphics/android/QueuedOperation.h17
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.cpp102
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.h6
-rw-r--r--WebCore/platform/graphics/android/TileSet.h77
-rw-r--r--WebCore/platform/graphics/android/TiledPage.cpp135
-rw-r--r--WebCore/platform/graphics/android/TiledPage.h11
-rw-r--r--WebCore/platform/graphics/android/TilesManager.h11
-rw-r--r--WebKit/Android.mk1
-rw-r--r--WebKit/android/RenderSkinAndroid.cpp13
-rw-r--r--WebKit/android/RenderSkinAndroid.h31
-rw-r--r--WebKit/android/RenderSkinButton.cpp73
-rw-r--r--WebKit/android/RenderSkinButton.h12
-rw-r--r--WebKit/android/RenderSkinMediaButton.cpp5
-rw-r--r--WebKit/android/RenderSkinNinePatch.cpp89
-rw-r--r--WebKit/android/RenderSkinNinePatch.h48
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp4
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.h4
-rw-r--r--WebKit/android/nav/WebView.cpp23
31 files changed, 494 insertions, 389 deletions
diff --git a/Android.mk b/Android.mk
index 0bddbc1..51640aa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -451,7 +451,6 @@ endif # JAVASCRIPT_ENGINE == jsc
# will strip out any unused code from the entry point.
include $(CLEAR_VARS)
# if you need to make webcore huge (for debugging), enable this line
-#LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libwebcore
LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index feeb56b..5bc6d83 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -620,6 +620,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/MediaLayer.cpp \
platform/graphics/android/MediaTexture.cpp \
platform/graphics/android/PaintLayerOperation.cpp \
+ platform/graphics/android/PaintTileOperation.cpp \
platform/graphics/android/PathAndroid.cpp \
platform/graphics/android/PatternAndroid.cpp \
platform/graphics/android/PlatformGraphicsContext.cpp \
@@ -630,7 +631,6 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
platform/graphics/android/TexturesGenerator.cpp \
platform/graphics/android/TilesManager.cpp \
platform/graphics/android/TiledPage.cpp \
- platform/graphics/android/TileSet.cpp \
platform/graphics/android/VideoLayerAndroid.cpp \
platform/graphics/android/android_graphics.cpp \
diff --git a/WebCore/platform/android/RenderThemeAndroid.cpp b/WebCore/platform/android/RenderThemeAndroid.cpp
index 944504e..113fa63 100644
--- a/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -44,6 +44,7 @@
#include "RenderSkinRadio.h"
#include "SkCanvas.h"
#include "UserAgentStyleSheets.h"
+#include "WebCoreFrameBridge.h"
namespace WebCore {
@@ -67,6 +68,13 @@ static SkCanvas* getCanvasFromInfo(const PaintInfo& info)
return info.context->platformContext()->mCanvas;
}
+static android::WebFrame* getWebFrame(const Node* node)
+{
+ if (!node)
+ return 0;
+ return android::WebFrame::getWebFrame(node->document()->frame());
+}
+
RenderTheme* theme()
{
DEFINE_STATIC_LOCAL(RenderThemeAndroid, androidTheme, ());
@@ -223,9 +231,15 @@ bool RenderThemeAndroid::paintButton(RenderObject* obj, const PaintInfo& info, c
// If it is a disabled button, simply paint it to the master picture.
Node* node = obj->node();
Element* formControlElement = static_cast<Element*>(node);
- if (formControlElement && !formControlElement->isEnabledFormControl())
- RenderSkinButton::Draw(getCanvasFromInfo(info), rect, RenderSkinAndroid::kDisabled);
- else
+ if (formControlElement && !formControlElement->isEnabledFormControl()) {
+ android::WebFrame* webFrame = getWebFrame(node);
+ if (webFrame) {
+ const RenderSkinAndroid* skins = webFrame->renderSkins();
+ if (skins)
+ skins->renderSkinButton()->draw(getCanvasFromInfo(info), rect,
+ RenderSkinAndroid::kDisabled);
+ }
+ } else
// Store all the important information in the platform context.
info.context->platformContext()->storeButtonInfo(node, rect);
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index 1786d64..cf8b6fa 100644
--- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -163,13 +163,19 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double
zooming = true;
}
+ // Display the current page
+ TiledPage* tiledPage = m_glWebViewState->frontPage();
+ tiledPage->setScale(m_glWebViewState->currentScale());
+
// Let's prepare the page if needed
if (prepareNextTiledPage) {
TiledPage* nextTiledPage = m_glWebViewState->backPage();
nextTiledPage->setScale(scale);
m_glWebViewState->setFutureViewport(viewportTileBounds);
m_glWebViewState->lockBaseLayerUpdate();
- nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, true);
+ nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds);
+ // Cancel pending paints for the foreground page
+ TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
}
float transparency = 1;
@@ -205,9 +211,6 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double
}
}
- // Display the current page
- TiledPage* tiledPage = m_glWebViewState->frontPage();
- tiledPage->setScale(m_glWebViewState->currentScale());
const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
TiledPage* nextTiledPage = m_glWebViewState->backPage();
@@ -240,7 +243,8 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double
if (!zooming)
m_glWebViewState->unlockBaseLayerUpdate();
- tiledPage->prepare(goingDown, goingLeft, preZoomBounds, true);
+ if (!prepareNextTiledPage)
+ tiledPage->prepare(goingDown, goingLeft, preZoomBounds);
tiledPage->draw(transparency, preZoomBounds);
}
diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp
index 391e87b..be0ccf6 100644
--- a/WebCore/platform/graphics/android/BaseTile.cpp
+++ b/WebCore/platform/graphics/android/BaseTile.cpp
@@ -66,6 +66,7 @@ BaseTile::BaseTile()
, m_texture(0)
, m_scale(1)
, m_dirty(true)
+ , m_repaintPending(false)
, m_usable(true)
, m_lastDirtyPicture(0)
, m_fullRepaintA(true)
@@ -166,12 +167,31 @@ bool BaseTile::isDirty()
return m_dirty;
}
+bool BaseTile::isRepaintPending()
+{
+ android::AutoMutex lock(m_atomicSync);
+ return m_repaintPending;
+}
+
+void BaseTile::setRepaintPending(bool pending)
+{
+ android::AutoMutex lock(m_atomicSync);
+ m_repaintPending = pending;
+}
+
void BaseTile::setUsedLevel(int usedLevel)
{
if (m_texture)
m_texture->setUsedLevel(usedLevel);
}
+int BaseTile::usedLevel()
+{
+ if (m_texture)
+ return m_texture->usedLevel();
+ return -1;
+}
+
void BaseTile::draw(float transparency, SkRect& rect)
{
if (m_x < 0 || m_y < 0)
diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h
index c50f6f5..709e3cf 100644
--- a/WebCore/platform/graphics/android/BaseTile.h
+++ b/WebCore/platform/graphics/android/BaseTile.h
@@ -72,6 +72,7 @@ public:
void reserveTexture();
void setUsedLevel(int);
+ int usedLevel();
bool isTileReady();
void draw(float transparency, SkRect& rect);
@@ -89,6 +90,8 @@ public:
void markAsDirty(const unsigned int pictureCount,
const SkRegion& dirtyArea);
bool isDirty();
+ bool isRepaintPending();
+ void setRepaintPending(bool pending);
void setUsable(bool usable);
float scale() const { return m_scale; }
void setScale(float scale);
@@ -114,6 +117,8 @@ private:
float m_scale;
// used to signal that the that the tile is out-of-date and needs to be redrawn
bool m_dirty;
+ // used to signal that a repaint is pending
+ bool m_repaintPending;
// used to signal whether or not the draw can use this tile.
bool m_usable;
// stores the id of the latest picture from webkit that caused this tile to
diff --git a/WebCore/platform/graphics/android/FontAndroid.cpp b/WebCore/platform/graphics/android/FontAndroid.cpp
index ffaeded..e896a46 100644
--- a/WebCore/platform/graphics/android/FontAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -83,8 +83,9 @@ static bool setupForText(SkPaint* paint, GraphicsContext* gc,
float shadowBlur;
Color shadowColor;
bool hasShadow = gc->getShadow(shadowOffset, shadowBlur, shadowColor);
-
- if (hasShadow || (mode == (cTextStroke & cTextFill))) {
+ bool hasBothStrokeAndFill =
+ (mode & (cTextStroke | cTextFill)) == (cTextStroke | cTextFill);
+ if (hasShadow || hasBothStrokeAndFill) {
SkLayerDrawLooper* looper = new SkLayerDrawLooper;
paint->setLooper(looper)->unref();
diff --git a/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
index 352516b..337a94d 100644
--- a/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
+++ b/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
@@ -163,11 +163,15 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
if (!(ts > 0))
ts = 12;
+ if (hashTableDeletedFontValue() == mTypeface)
+ paint->setTypeface(0);
+ else
+ paint->setTypeface(mTypeface);
+
paint->setAntiAlias(true);
paint->setSubpixelText(true);
paint->setHinting(SkPaint::kSlight_Hinting);
paint->setTextSize(SkFloatToScalar(ts));
- paint->setTypeface(mTypeface);
paint->setFakeBoldText(mFakeBold);
paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
#ifndef SUPPORT_COMPLEX_SCRIPTS
@@ -177,7 +181,10 @@ void FontPlatformData::setupPaint(SkPaint* paint) const
uint32_t FontPlatformData::uniqueID() const
{
- return mTypeface->uniqueID();
+ if (hashTableDeletedFontValue() == mTypeface)
+ return SkTypeface::UniqueID(0);
+ else
+ return SkTypeface::UniqueID(mTypeface);
}
bool FontPlatformData::operator==(const FontPlatformData& a) const
@@ -207,7 +214,10 @@ unsigned FontPlatformData::hash() const
bool FontPlatformData::isFixedPitch() const
{
- return mTypeface ? mTypeface->isFixedWidth() : false;
+ if (mTypeface && (mTypeface != hashTableDeletedFontValue()))
+ return mTypeface->isFixedWidth();
+ else
+ return false;
}
HB_FaceRec_* FontPlatformData::harfbuzzFace() const
diff --git a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
index 1a32ef5..64b6ad3 100644
--- a/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
+++ b/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
@@ -101,10 +101,16 @@ static bool setBitmapDash(SkPaint* paint, int width) {
// Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor()
struct ShadowRec {
- SkScalar blur; // >0 means valid shadow
+ SkScalar blur;
SkScalar dx;
SkScalar dy;
- SkColor color;
+ SkColor color; // alpha>0 means valid shadow
+ ShadowRec(SkScalar b = 0,
+ SkScalar x = 0,
+ SkScalar y = 0,
+ SkColor c = 0) // by default, alpha=0, so no shadow
+ : blur(b), dx(x), dy(y), color(c)
+ {};
};
class GraphicsContextPlatformPrivate {
@@ -141,7 +147,6 @@ public:
, strokeColor(SK_ColorBLACK)
, useAA(true)
{
- shadow.blur = 0;
}
State(const State& other)
@@ -283,7 +288,7 @@ public:
paint->setAntiAlias(m_state->useAA);
paint->setDither(true);
paint->setXfermodeMode(m_state->mode);
- if (m_state->shadow.blur > 0) {
+ if (SkColorGetA(m_state->shadow.color) > 0) {
SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
m_state->shadow.dx,
m_state->shadow.dy,
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
index 6a43745..becfe02 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -890,7 +890,7 @@ void LayerAndroid::createGLTextures()
uniqueId(), this, m_dirty, m_reservedTexture,
m_reservedTexture->rect().width(), m_reservedTexture->rect().height());
PaintLayerOperation* operation = new PaintLayerOperation(this);
- TilesManager::instance()->scheduleOperation(operation, !m_drawingTexture);
+ TilesManager::instance()->scheduleOperation(operation);
} else {
XLOG("We don't schedule a paint for layer %d (%x), because we already sent a request",
uniqueId(), this);
diff --git a/WebCore/platform/graphics/android/TileSet.cpp b/WebCore/platform/graphics/android/PaintTileOperation.cpp
index 1214aa2..222b69b 100644
--- a/WebCore/platform/graphics/android/TileSet.cpp
+++ b/WebCore/platform/graphics/android/PaintTileOperation.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2011, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,64 +24,58 @@
*/
#include "config.h"
-#include "TileSet.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "ClassTracker.h"
-#include "TilesManager.h"
-
-#ifdef DEBUG
-
-#include <cutils/log.h>
-#include <wtf/CurrentTime.h>
-#include <wtf/text/CString.h>
-
-#undef XLOG
-#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TileSet", __VA_ARGS__)
-
-#else
-
-#undef XLOG
-#define XLOG(...)
-
-#endif // DEBUG
+#include "PaintTileOperation.h"
namespace WebCore {
-TileSet::TileSet(TiledPage* tiledPage, int rows, int cols)
- : m_tiledPage(tiledPage)
- , m_nbRows(rows)
- , m_nbCols(cols)
+PaintTileOperation::PaintTileOperation(BaseTile* tile)
+ : QueuedOperation(QueuedOperation::PaintTile, tile->page())
+ , m_tile(tile)
{
-#ifdef DEBUG_COUNT
- ClassTracker::instance()->increment("TileSet");
-#endif
+ if (m_tile)
+ m_tile->setRepaintPending(true);
}
-TileSet::~TileSet()
+PaintTileOperation::~PaintTileOperation()
{
-#ifdef DEBUG_COUNT
- ClassTracker::instance()->decrement("TileSet");
-#endif
+ if (m_tile) {
+ m_tile->setRepaintPending(false);
+ m_tile = 0;
+ }
}
-bool TileSet::operator==(const TileSet& set)
+bool PaintTileOperation::operator==(const QueuedOperation* operation)
{
- return m_tiledPage == set.m_tiledPage
- && m_nbRows == set.m_nbRows
- && m_nbCols == set.m_nbCols;
+ if (operation->type() != type())
+ return false;
+ const PaintTileOperation* op = static_cast<const PaintTileOperation*>(operation);
+ return op->m_tile == m_tile;
}
-
-void TileSet::paint()
+void PaintTileOperation::run()
{
- XLOG("%x, painting %d tiles", this, m_tiles.size());
- for (unsigned int i = 0; i < m_tiles.size(); i++)
- m_tiles[i]->paintBitmap();
- XLOG("%x, end of painting %d tiles", this, m_tiles.size());
+ if (m_tile) {
+ m_tile->paintBitmap();
+ m_tile->setRepaintPending(false);
+ m_tile = 0;
+ }
}
-} // namespace WebCore
+int PaintTileOperation::priority()
+{
+ if (!m_tile || m_tile->usedLevel() < 0)
+ return -1;
+ bool goingDown = m_tile->page()->scrollingDown();
+ SkIRect *rect = m_tile->page()->expandedTileBounds();
+ int firstTileX = rect->fLeft;
+ int nbTilesWidth = rect->width();
+ int priority = m_tile->x() - firstTileX;
+ if (goingDown)
+ priority += (rect->fBottom - m_tile->y()) * nbTilesWidth;
+ else
+ priority += (m_tile->y() - rect->fTop) * nbTilesWidth;
+ priority += m_tile->usedLevel() * 100000;
+ return priority;
+}
-#endif // USE(ACCELERATED_COMPOSITING)
+}
diff --git a/WebCore/platform/graphics/android/PaintTileSetOperation.h b/WebCore/platform/graphics/android/PaintTileOperation.h
index fba7220..0920f32 100644
--- a/WebCore/platform/graphics/android/PaintTileSetOperation.h
+++ b/WebCore/platform/graphics/android/PaintTileOperation.h
@@ -27,33 +27,19 @@
#define PaintTileSetOperation_h
#include "QueuedOperation.h"
-#include "TileSet.h"
namespace WebCore {
-class PaintTileSetOperation : public QueuedOperation {
+class PaintTileOperation : public QueuedOperation {
public:
- PaintTileSetOperation(TileSet* set)
- : QueuedOperation(QueuedOperation::PaintTileSet, set->page())
- , m_set(set) {}
- virtual ~PaintTileSetOperation()
- {
- delete m_set;
- }
- virtual bool operator==(const QueuedOperation* operation)
- {
- if (operation->type() != type())
- return false;
- const PaintTileSetOperation* op = static_cast<const PaintTileSetOperation*>(operation);
- return op->m_set == m_set;
- }
- virtual void run()
- {
- if (m_set)
- m_set->paint();
- }
+ PaintTileOperation(BaseTile* tile);
+ virtual ~PaintTileOperation();
+ virtual bool operator==(const QueuedOperation* operation);
+ virtual void run();
+ virtual int priority();
+
private:
- TileSet* m_set;
+ BaseTile* m_tile;
};
}
diff --git a/WebCore/platform/graphics/android/PlatformGraphicsContext.h b/WebCore/platform/graphics/android/PlatformGraphicsContext.h
index 8d0df36..0ce86d2 100644
--- a/WebCore/platform/graphics/android/PlatformGraphicsContext.h
+++ b/WebCore/platform/graphics/android/PlatformGraphicsContext.h
@@ -106,7 +106,8 @@ public:
// corresponds to the focused node passed in. If its state has changed,
// re-record to the subpicture, so the master picture will reflect the
// change.
- void updateFocusState(WebCore::RenderSkinAndroid::State state)
+ void updateFocusState(WebCore::RenderSkinAndroid::State state,
+ const WebCore::RenderSkinButton* buttonSkin)
{
if (state == m_state)
return;
@@ -117,8 +118,8 @@ public:
state == WebCore::RenderSkinAndroid::kFocused)
return;
m_state = state;
- SkCanvas* canvas = m_picture->beginRecording(m_rect.width(), m_rect.height());
- WebCore::RenderSkinButton::Draw(canvas, m_rect, state);
+ SkCanvas* canvas = m_picture->beginRecording(m_rect.right(), m_rect.bottom());
+ buttonSkin->draw(canvas, m_rect, state);
m_picture->endRecording();
}
private:
diff --git a/WebCore/platform/graphics/android/QueuedOperation.h b/WebCore/platform/graphics/android/QueuedOperation.h
index 089483d..98f3e2f 100644
--- a/WebCore/platform/graphics/android/QueuedOperation.h
+++ b/WebCore/platform/graphics/android/QueuedOperation.h
@@ -32,13 +32,14 @@ namespace WebCore {
class QueuedOperation {
public:
- enum OperationType { Undefined, PaintTileSet, PaintLayer, DeleteTexture };
+ enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture };
QueuedOperation(OperationType type, TiledPage* page)
: m_type(type)
, m_page(page) {}
virtual ~QueuedOperation() {}
virtual void run() = 0;
virtual bool operator==(const QueuedOperation* operation) = 0;
+ virtual int priority() { return -1; }
OperationType type() const { return m_type; }
TiledPage* page() const { return m_page; }
private:
@@ -65,6 +66,20 @@ class PageFilter : public OperationFilter {
TiledPage* m_page;
};
+class PagePaintFilter : public OperationFilter {
+ public:
+ PagePaintFilter(TiledPage* page) : m_page(page) {}
+ virtual bool check(QueuedOperation* operation)
+ {
+ if (operation->type() == QueuedOperation::PaintTile
+ && operation->page() == m_page)
+ return true;
+ return false;
+ }
+ private:
+ TiledPage* m_page;
+};
+
}
#endif // QueuedOperation_h
diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp
index ad5de1f..e6bef6a 100644
--- a/WebCore/platform/graphics/android/TexturesGenerator.cpp
+++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp
@@ -51,27 +51,11 @@
namespace WebCore {
-void TexturesGenerator::scheduleOperation(QueuedOperation* operation, bool scheduleFirst)
+void TexturesGenerator::scheduleOperation(QueuedOperation* operation)
{
{
android::Mutex::Autolock lock(mRequestedOperationsLock);
- for (unsigned int i = 0; i < mRequestedOperations.size(); i++) {
- QueuedOperation** s = &mRequestedOperations[i];
- // A similar operation is already in the queue. The newer operation may
- // have additional dirty tiles so delete the existing operation and
- // replace it with the new one.
- if (*s && *s == operation) {
- QueuedOperation* oldOperation = *s;
- *s = operation;
- delete oldOperation;
- return;
- }
- }
-
- if (scheduleFirst)
- mRequestedOperations.prepend(operation);
- else
- mRequestedOperations.append(operation);
+ mRequestedOperations.append(operation);
}
mRequestedOperationsCond.signal();
}
@@ -81,6 +65,11 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page)
removeOperationsForFilter(new PageFilter(page));
}
+void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning)
+{
+ removeOperationsForFilter(new PagePaintFilter(page), waitForRunning);
+}
+
void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer)
{
removeOperationsForFilter(new PaintLayerBaseFilter(layer));
@@ -93,6 +82,11 @@ void TexturesGenerator::removeOperationsForTexture(LayerTexture* texture)
void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
{
+ removeOperationsForFilter(filter, true);
+}
+
+void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning)
+{
android::Mutex::Autolock lock(mRequestedOperationsLock);
for (unsigned int i = 0; i < mRequestedOperations.size();) {
QueuedOperation* operation = mRequestedOperations[i];
@@ -104,18 +98,22 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
}
}
- QueuedOperation* operation = m_currentOperation;
- if (operation && filter->check(operation))
- m_waitForCompletion = true;
-
- delete filter;
-
- // At this point, it means that we are currently executing an operation that
- // we want to be removed -- we should wait until it is done, so that
- // when we return our caller can be sure that there is no more operations
- // in the queue matching the given filter.
- while (m_waitForCompletion)
- mRequestedOperationsCond.wait(mRequestedOperationsLock);
+ if (waitForRunning) {
+ QueuedOperation* operation = m_currentOperation;
+ if (operation && filter->check(operation))
+ m_waitForCompletion = true;
+
+ delete filter;
+
+ // At this point, it means that we are currently executing an operation that
+ // we want to be removed -- we should wait until it is done, so that
+ // when we return our caller can be sure that there is no more operations
+ // in the queue matching the given filter.
+ while (m_waitForCompletion)
+ mRequestedOperationsCond.wait(mRequestedOperationsLock);
+ } else {
+ delete filter;
+ }
}
status_t TexturesGenerator::readyToRun()
@@ -125,6 +123,37 @@ status_t TexturesGenerator::readyToRun()
return NO_ERROR;
}
+// Must be called from within a lock!
+QueuedOperation* TexturesGenerator::popNext()
+{
+ // Priority can change between when it was added and now
+ // Hence why the entire queue is rescanned
+ QueuedOperation* current = mRequestedOperations.last();
+ int currentPriority = current->priority();
+ if (currentPriority < 0) {
+ mRequestedOperations.removeLast();
+ return current;
+ }
+ int currentIndex = mRequestedOperations.size() - 1;
+ // Scan from the back to make removing faster (less items to copy)
+ for (int i = mRequestedOperations.size() - 2; i >= 0; i--) {
+ QueuedOperation *next = mRequestedOperations[i];
+ int nextPriority = next->priority();
+ if (nextPriority < 0) {
+ // Found a very high priority item, go ahead and just handle it now
+ mRequestedOperations.remove(i);
+ return next;
+ }
+ if (nextPriority < currentPriority) {
+ current = next;
+ currentPriority = nextPriority;
+ currentIndex = i;
+ }
+ }
+ mRequestedOperations.remove(currentIndex);
+ return current;
+}
+
bool TexturesGenerator::threadLoop()
{
// Check if we have any pending operations.
@@ -138,20 +167,14 @@ bool TexturesGenerator::threadLoop()
m_currentOperation = 0;
bool stop = false;
while (!stop) {
- XLOG("threadLoop evaluating the requests");
mRequestedOperationsLock.lock();
- if (mRequestedOperations.size()) {
- m_currentOperation = mRequestedOperations.first();
- mRequestedOperations.remove(0);
- XLOG("threadLoop, popping the first request (%d requests left)",
- mRequestedOperations.size());
- }
+ if (mRequestedOperations.size())
+ m_currentOperation = popNext();
mRequestedOperationsLock.unlock();
if (m_currentOperation) {
- XLOG("threadLoop, painting the request");
+ XLOG("threadLoop, painting the request with priority %d", m_currentOperation->priority());
m_currentOperation->run();
- XLOG("threadLoop, painting the request - DONE");
}
mRequestedOperationsLock.lock();
@@ -168,6 +191,7 @@ bool TexturesGenerator::threadLoop()
mRequestedOperationsLock.unlock();
}
+ XLOG("threadLoop empty");
return true;
}
diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h
index 169471c..b03f52d 100644
--- a/WebCore/platform/graphics/android/TexturesGenerator.h
+++ b/WebCore/platform/graphics/android/TexturesGenerator.h
@@ -30,7 +30,6 @@
#include "LayerTexture.h"
#include "QueuedOperation.h"
-#include "TileSet.h"
#include "TiledPage.h"
#include <utils/threads.h>
@@ -52,11 +51,14 @@ public:
void removeOperationsForPage(TiledPage* page);
void removeOperationsForBaseLayer(BaseLayerAndroid* layer);
void removeOperationsForTexture(LayerTexture* texture);
+ void removePaintOperationsForPage(TiledPage* page, bool waitForRunning);
void removeOperationsForFilter(OperationFilter* filter);
+ void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning);
- void scheduleOperation(QueuedOperation* operation, bool scheduleFirst);
+ void scheduleOperation(QueuedOperation* operation);
private:
+ QueuedOperation* popNext();
virtual bool threadLoop();
Vector<QueuedOperation*> mRequestedOperations;
android::Mutex mRequestedOperationsLock;
diff --git a/WebCore/platform/graphics/android/TileSet.h b/WebCore/platform/graphics/android/TileSet.h
deleted file mode 100644
index aa0f2ed..0000000
--- a/WebCore/platform/graphics/android/TileSet.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 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 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
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TileSet_h
-#define TileSet_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "BaseTile.h"
-#include "Vector.h"
-
-namespace WebCore {
-
-/**
- * This purpose of this class is to act as a container for BaseTiles that need
- * to upload their contents to the GPU. A TiledPage creates a new TileSet and
- * provides the set with identifying characteristics of the TiledPage's current
- * state (see constructor). This information allows the consumer of the TileSet
- * to determine if an equivalent TileSet already exists in the upload pipeline.
- */
-class TileSet {
-public:
- TileSet(TiledPage* tiledPage, int nbRows, int nbCols);
- ~TileSet();
-
- bool operator==(const TileSet& set);
- void paint();
-
- void add(BaseTile* texture)
- {
- m_tiles.append(texture);
- }
-
- TiledPage* page()
- {
- return m_tiledPage;
- }
-
- unsigned int size()
- {
- return m_tiles.size();
- }
-
-private:
- Vector<BaseTile*> m_tiles;
-
- TiledPage* m_tiledPage;
- int m_nbRows;
- int m_nbCols;
-};
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
-#endif // TileSet_h
diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp
index 21afe24..0251b03 100644
--- a/WebCore/platform/graphics/android/TiledPage.cpp
+++ b/WebCore/platform/graphics/android/TiledPage.cpp
@@ -30,7 +30,7 @@
#include "GLUtils.h"
#include "IntRect.h"
-#include "PaintTileSetOperation.h"
+#include "PaintTileOperation.h"
#include "TilesManager.h"
#ifdef DEBUG
@@ -82,7 +82,6 @@ void TiledPage::updateBaseTileSize()
int baseTileSize = TilesManager::instance()->maxTextureCount() + 1;
if (baseTileSize > m_baseTileSize)
m_baseTileSize = baseTileSize;
- XLOG("Allocate %d tiles", m_baseTileSize);
}
TiledPage::~TiledPage()
@@ -126,6 +125,7 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC
const int lastDirtyTileX = static_cast<int>(ceilf(inval.right() * invTileContentWidth));
const int lastDirtyTileY = static_cast<int>(ceilf(inval.bottom() * invTileContentHeight));
+ XLOG("Marking X %d-%d and Y %d-%d dirty", firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY);
// We defer marking the tile as dirty until the next time we need to prepare
// to draw.
m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op);
@@ -133,12 +133,10 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC
m_latestPictureInval = pictureCount;
}
-void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set)
+void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds)
{
if (y < 0)
return;
- if (!set)
- return;
for (int i = 0; i < tilesInRow; i++) {
int x = firstTileX;
@@ -177,12 +175,41 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y
// ensure there is a texture associated with the tile and then check to
// see if the texture is dirty and in need of repainting
currentTile->reserveTexture();
- if (currentTile->isDirty())
- set->add(currentTile);
+ updateTileUsedLevel(tileBounds, *currentTile);
+ if (currentTile->isDirty() && !currentTile->isRepaintPending()) {
+ PaintTileOperation *operation = new PaintTileOperation(currentTile);
+ TilesManager::instance()->scheduleOperation(operation);
+ } else if (currentTile->isDirty()) {
+ XLOG("Tile %dx%d is dirty, but awaiting repaint", currentTile->x(), currentTile->y());
+ }
}
}
}
+void TiledPage::updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile)
+{
+ const int lastTileX = tileBounds.fRight - 1;
+ const int lastTileY = tileBounds.fBottom - 1;
+
+ // set the used level of the tile (e.g. distance from the viewport)
+ int dx = 0;
+ int dy = 0;
+
+ if (tileBounds.fLeft > tile.x())
+ dx = tileBounds.fLeft - tile.x();
+ else if (lastTileX < tile.x())
+ dx = tile.x() - lastTileX;
+
+ if (tileBounds.fTop > tile.y())
+ dy = tileBounds.fTop - tile.y();
+ else if (lastTileY < tile.y())
+ dy = tile.y() - lastTileY;
+
+ int d = std::max(dx, dy);
+
+ tile.setUsedLevel(d);
+}
+
void TiledPage::updateTileState(const SkIRect& tileBounds)
{
if (!m_glWebViewState || tileBounds.isEmpty()) {
@@ -191,41 +218,19 @@ void TiledPage::updateTileState(const SkIRect& tileBounds)
return;
}
- const int nbTilesWidth = tileBounds.width() - 1;
- const int nbTilesHeight = tileBounds.height() - 1;
-
- const int lastTileX = tileBounds.fRight - 1;
- const int lastTileY = tileBounds.fBottom - 1;
-
for (int x = 0; x < m_baseTileSize; x++) {
BaseTile& tile = m_baseTiles[x];
- // if the tile is in the dirty region then we must invalidate it
- if (m_invalRegion.contains(tile.x(), tile.y()))
- tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion);
-
// if the tile no longer has a texture then proceed to the next tile
if (tile.isAvailable())
continue;
- // set the used level of the tile (e.g. distance from the viewport)
- int dx = 0;
- int dy = 0;
-
- if (tileBounds.fLeft > tile.x())
- dx = tileBounds.fLeft - tile.x();
- else if (lastTileX < tile.x())
- dx = tile.x() - lastTileX;
-
- if (tileBounds.fTop > tile.y())
- dy = tileBounds.fTop - tile.y();
- else if (lastTileY < tile.y())
- dy = tile.y() - lastTileY;
-
- int d = std::max(dx, dy);
+ // if the tile is in the dirty region then we must invalidate it
+ if (m_invalRegion.contains(tile.x(), tile.y()))
+ tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion);
- tile.setUsedLevel(d);
+ updateTileUsedLevel(tileBounds, tile);
}
// clear the invalidated region as all tiles within that region have now
@@ -234,8 +239,7 @@ void TiledPage::updateTileState(const SkIRect& tileBounds)
m_invalTilesRegion.setEmpty();
}
-void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds,
- bool scheduleFirst)
+void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds)
{
if (!m_glWebViewState)
return;
@@ -243,6 +247,7 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
// update the tiles distance from the viewport
updateTileState(tileBounds);
m_prepare = true;
+ m_scrollingDown = goingDown;
int firstTileX = tileBounds.fLeft;
int firstTileY = tileBounds.fTop;
@@ -255,43 +260,29 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
const int baseContentHeight = m_glWebViewState->baseContentHeight();
const int baseContentWidth = m_glWebViewState->baseContentWidth();
- TileSet* set = new TileSet(this, nbTilesHeight, nbTilesWidth);
-
- if (!scheduleFirst) {
- // Expand number of tiles to allow tiles outside of viewport to be prepared for
- // smoother scrolling.
- int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
- int nMaxTilesPerPage = m_baseTileSize / 2;
- int expandX = TilesManager::instance()->expandedTileBoundsX();
- int expandY = TilesManager::instance()->expandedTileBoundsY();
- if (nTilesToPrepare + (nbTilesHeight * expandX * 2) <= nMaxTilesPerPage) {
- firstTileX -= expandX;
- lastTileX += expandX;
- nbTilesWidth += expandX * 2;
- }
- if (nTilesToPrepare + (nbTilesWidth * expandY * 2) <= nMaxTilesPerPage) {
- firstTileY -= expandY;
- lastTileY += expandY;
- nbTilesHeight += expandY * 2;
- }
+ // Expand number of tiles to allow tiles outside of viewport to be prepared for
+ // smoother scrolling.
+ int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
+ int nMaxTilesPerPage = m_baseTileSize / 2;
+ int expandX = TilesManager::instance()->expandedTileBoundsX();
+ int expandY = TilesManager::instance()->expandedTileBoundsY();
+ if (nTilesToPrepare + (nbTilesHeight * expandX * 2) <= nMaxTilesPerPage) {
+ firstTileX -= expandX;
+ lastTileX += expandX;
+ nbTilesWidth += expandX * 2;
}
-
- // We chose to prepare tiles depending on the scroll direction. Tiles are
- // appended to the list and the texture uploader goes through the list front
- // to back. So we append tiles in reverse order because the last additions
- // to the are processed first.
- if (goingDown) {
- for (int i = 0; i < nbTilesHeight; i++)
- prepareRow(goingLeft, nbTilesWidth, firstTileX, lastTileY - i, set);
- } else {
- for (int i = 0; i < nbTilesHeight; i++)
- prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, set);
+ if (nTilesToPrepare + (nbTilesWidth * expandY * 2) <= nMaxTilesPerPage) {
+ firstTileY -= expandY;
+ lastTileY += expandY;
+ nbTilesHeight += expandY * 2;
}
+ m_expandedTileBounds.fLeft = firstTileX;
+ m_expandedTileBounds.fTop = firstTileY;
+ m_expandedTileBounds.fRight = lastTileX;
+ m_expandedTileBounds.fBottom = lastTileY;
- // The paint operation will take ownership of the tileSet here, so no delete
- // is necessary.
- PaintTileSetOperation* operation = new PaintTileSetOperation(set);
- TilesManager::instance()->scheduleOperation(operation, scheduleFirst);
+ for (int i = 0; i < nbTilesHeight; i++)
+ prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, tileBounds);
}
bool TiledPage::ready(const SkIRect& tileBounds, float scale)
@@ -330,7 +321,6 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds)
actualTileBounds.fLeft -= TilesManager::instance()->expandedTileBoundsX();
actualTileBounds.fRight += TilesManager::instance()->expandedTileBoundsX();
- XLOG("WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency);
for (int j = 0; j < m_baseTileSize; j++) {
BaseTile& tile = m_baseTiles[j];
if (actualTileBounds.contains(tile.x(), tile.y())) {
@@ -344,11 +334,6 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds)
tile.draw(transparency, rect);
}
}
-
-#ifdef DEBUG
- XLOG("FINISHED WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency);
- TilesManager::instance()->printTextures();
-#endif // DEBUG
}
unsigned int TiledPage::paintBaseLayerContent(SkCanvas* canvas)
diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h
index 7e0bb2e..1aa3e61 100644
--- a/WebCore/platform/graphics/android/TiledPage.h
+++ b/WebCore/platform/graphics/android/TiledPage.h
@@ -31,7 +31,6 @@
#include "BaseTile.h"
#include "SkCanvas.h"
#include "SkRegion.h"
-#include "TileSet.h"
namespace WebCore {
@@ -57,8 +56,7 @@ public:
TiledPage* sibling();
// prepare the page for display on the screen
- void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds,
- bool scheduleFirst = false);
+ void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds);
// check to see if the page is ready for display
bool ready(const SkIRect& tileBounds, float scale);
// draw the page on the screen
@@ -75,10 +73,13 @@ public:
void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount);
void setUsable(bool usable);
void updateBaseTileSize();
+ bool scrollingDown() { return m_scrollingDown; }
+ SkIRect* expandedTileBounds() { return &m_expandedTileBounds; }
private:
void updateTileState(const SkIRect& tileBounds);
- void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set);
+ void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds);
+ void updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile);
BaseTile* getBaseTile(int x, int y) const;
@@ -103,6 +104,8 @@ private:
SkRegion m_invalTilesRegion;
unsigned int m_latestPictureInval;
bool m_prepare;
+ bool m_scrollingDown;
+ SkIRect m_expandedTileBounds;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h
index 5a4e28a..6d49cca 100644
--- a/WebCore/platform/graphics/android/TilesManager.h
+++ b/WebCore/platform/graphics/android/TilesManager.h
@@ -39,8 +39,6 @@
namespace WebCore {
-class TileSet;
-
class TilesManager {
public:
static TilesManager* instance();
@@ -57,6 +55,11 @@ public:
m_pixmapsGenerationThread->removeOperationsForPage(page);
}
+ void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion)
+ {
+ m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion);
+ }
+
void removeOperationsForBaseLayer(BaseLayerAndroid* layer)
{
m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer);
@@ -67,9 +70,9 @@ public:
m_pixmapsGenerationThread->removeOperationsForTexture(texture);
}
- void scheduleOperation(QueuedOperation* operation, bool scheduleFirst = false)
+ void scheduleOperation(QueuedOperation* operation)
{
- m_pixmapsGenerationThread->scheduleOperation(operation, scheduleFirst);
+ m_pixmapsGenerationThread->scheduleOperation(operation);
}
ShaderProgram* shader() { return &m_shader; }
diff --git a/WebKit/Android.mk b/WebKit/Android.mk
index 88defda..5998227 100644
--- a/WebKit/Android.mk
+++ b/WebKit/Android.mk
@@ -53,6 +53,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
android/RenderSkinButton.cpp \
android/RenderSkinCombo.cpp \
android/RenderSkinMediaButton.cpp \
+ android/RenderSkinNinePatch.cpp \
android/RenderSkinRadio.cpp \
android/TimeCounter.cpp \
\
diff --git a/WebKit/android/RenderSkinAndroid.cpp b/WebKit/android/RenderSkinAndroid.cpp
index 00f2b96..9383a9c 100644
--- a/WebKit/android/RenderSkinAndroid.cpp
+++ b/WebKit/android/RenderSkinAndroid.cpp
@@ -37,15 +37,14 @@
#include "utils/Asset.h"
namespace WebCore {
-
-RenderSkinAndroid::RenderSkinAndroid()
- : m_height(0)
- , m_width(0)
-{}
-void RenderSkinAndroid::Init(android::AssetManager* am, String drawableDirectory)
+RenderSkinAndroid::~RenderSkinAndroid()
{
- RenderSkinButton::Init(am, drawableDirectory);
+ delete m_button;
+}
+RenderSkinAndroid::RenderSkinAndroid(android::AssetManager* am, String drawableDirectory)
+{
+ m_button = new RenderSkinButton(am, drawableDirectory);
RenderSkinCombo::Init(am, drawableDirectory);
RenderSkinMediaButton::Init(am, drawableDirectory);
RenderSkinRadio::Init(am, drawableDirectory);
diff --git a/WebKit/android/RenderSkinAndroid.h b/WebKit/android/RenderSkinAndroid.h
index b877ff2..73773ea 100644
--- a/WebKit/android/RenderSkinAndroid.h
+++ b/WebKit/android/RenderSkinAndroid.h
@@ -36,17 +36,11 @@ class SkBitmap;
namespace WebCore {
class Node;
-class PlatformGraphicsContext;
+class RenderSkinButton;
-/* RenderSkinAndroid is the base class for all RenderSkins. Form elements each have a
- * subclass for drawing themselves.
- */
class RenderSkinAndroid
{
public:
- RenderSkinAndroid();
- virtual ~RenderSkinAndroid() {}
-
enum State {
kDisabled,
kNormal,
@@ -60,7 +54,8 @@ public:
* Initialize the Android skinning system. The AssetManager may be used to find resources used
* in rendering.
*/
- static void Init(android::AssetManager*, String drawableDirectory);
+ RenderSkinAndroid(android::AssetManager*, String drawableDirectory);
+ ~RenderSkinAndroid();
/* DecodeBitmap determines which file to use, with the given fileName of the form
* "images/bitmap.png", and uses the asset manager to select the exact one. It
@@ -68,24 +63,10 @@ public:
*/
static bool DecodeBitmap(android::AssetManager* am, const char* fileName, SkBitmap* bitmap);
- /* draw() tells the skin to draw itself, and returns true if the skin needs
- * a redraw to animations, false otherwise
- */
- virtual bool draw(PlatformGraphicsContext*) { return false; }
-
- /* notifyState() checks to see if the element is checked, focused, and enabled
- * it must be implemented in the subclass
- */
- virtual void notifyState(Node* element) { }
-
- /* setDim() tells the skin its width and height
- */
- virtual void setDim(int width, int height) { m_width = width; m_height = height; }
-
-protected:
- int m_height;
- int m_width;
+ const RenderSkinButton* renderSkinButton() const { return m_button; }
+private:
+ RenderSkinButton* m_button;
};
} // WebCore
diff --git a/WebKit/android/RenderSkinButton.cpp b/WebKit/android/RenderSkinButton.cpp
index 1dc6560..6a0ae54 100644
--- a/WebKit/android/RenderSkinButton.cpp
+++ b/WebKit/android/RenderSkinButton.cpp
@@ -31,47 +31,36 @@
#include "IntRect.h"
#include "Node.h"
#include "RenderSkinButton.h"
+#include "RenderSkinNinePatch.h"
#include "SkCanvas.h"
#include "SkNinePatch.h"
#include "SkRect.h"
+#include <utils/Asset.h>
+#include <utils/AssetManager.h>
#include <utils/Debug.h>
#include <utils/Log.h>
+#include <utils/ResourceTypes.h>
#include <wtf/text/CString.h>
-struct PatchData {
- const char* name;
- int8_t outset, margin;
-};
-
-static const PatchData gFiles[] =
- {
- { "btn_default_disabled_holo.9.png", 2, 7 },
- { "btn_default_normal_holo.9.png", 2, 7 },
- { "btn_default_focused_holo.9.png", 2, 7 },
- { "btn_default_pressed_holo.9.png", 2, 7 }
+static const char* gFiles[] = {
+ "btn_default_disabled_holo.9.png",
+ "btn_default_normal_holo.9.png",
+ "btn_default_focused_holo.9.png",
+ "btn_default_pressed_holo.9.png"
};
-static SkBitmap gButton[sizeof(gFiles)/sizeof(gFiles[0])];
-static bool gDecoded;
-static bool gHighRes;
-
namespace WebCore {
-void RenderSkinButton::Init(android::AssetManager* am, String drawableDirectory)
+RenderSkinButton::RenderSkinButton(android::AssetManager* am, String drawableDirectory)
{
- static bool gInited;
- if (gInited)
- return;
-
- gInited = true;
- gDecoded = true;
- gHighRes = drawableDirectory[drawableDirectory.length() - 5] == 'h';
- for (size_t i = 0; i < sizeof(gFiles)/sizeof(gFiles[0]); i++) {
- String path = drawableDirectory + gFiles[i].name;
- if (!RenderSkinAndroid::DecodeBitmap(am, path.utf8().data(), &gButton[i])) {
- gDecoded = false;
- LOGD("RenderSkinButton::Init: button assets failed to decode\n\tBrowser buttons will not draw");
- break;
+ m_decoded = true;
+ for (size_t i = 0; i < 4; i++) {
+ String path = String(drawableDirectory.impl());
+ path.append(String(gFiles[i]));
+ if (!RenderSkinNinePatch::decodeAsset(am, path.utf8().data(), &m_buttons[i])) {
+ m_decoded = false;
+ LOGE("RenderSkinButton::Init: button assets failed to decode\n\tBrowser buttons will not draw");
+ return;
}
}
@@ -82,11 +71,12 @@ void RenderSkinButton::Init(android::AssetManager* am, String drawableDirectory)
android::CompileTimeAssert<(RenderSkinAndroid::kPressed == 3)> a4;
}
-void RenderSkinButton::Draw(SkCanvas* canvas, const IntRect& r, RenderSkinAndroid::State newState)
+void RenderSkinButton::draw(SkCanvas* canvas, const IntRect& r,
+ RenderSkinAndroid::State newState) const
{
// If we failed to decode, do nothing. This way the browser still works,
// and webkit will still draw the label and layout space for us.
- if (!gDecoded) {
+ if (!m_decoded) {
return;
}
@@ -94,26 +84,7 @@ void RenderSkinButton::Draw(SkCanvas* canvas, const IntRect& r, RenderSkinAndroi
SkASSERT(static_cast<unsigned>(newState) <
static_cast<unsigned>(RenderSkinAndroid::kNumStates));
- // Set up the ninepatch information for drawing.
- SkRect bounds(r);
- const PatchData& pd = gFiles[newState];
- int marginValue = pd.margin + pd.outset;
-
- SkIRect margin;
-
- margin.set(marginValue, marginValue, marginValue, marginValue);
- if (gHighRes) {
- /* FIXME: it shoudn't be necessary to offset the button here,
- but gives the right results. */
- bounds.offset(0, SK_Scalar1 * 2);
- /* FIXME: This temporarily gets around the fact that the margin values and
- positioning were created for a low res asset, which was used on
- g1-like devices. A better fix would be to read the offset information
- out of the png. */
- margin.set(10, 9, 10, 14);
- }
- // Draw to the canvas.
- SkNinePatch::DrawNine(canvas, bounds, gButton[newState], margin);
+ RenderSkinNinePatch::DrawNinePatch(canvas, SkRect(r), m_buttons[newState]);
}
} //WebCore
diff --git a/WebKit/android/RenderSkinButton.h b/WebKit/android/RenderSkinButton.h
index e9cf0ec..e9db74c 100644
--- a/WebKit/android/RenderSkinButton.h
+++ b/WebKit/android/RenderSkinButton.h
@@ -27,24 +27,28 @@
#define RenderSkinButton_h
#include "RenderSkinAndroid.h"
+#include "RenderSkinNinePatch.h"
class SkCanvas;
namespace WebCore {
class IntRect;
-class RenderSkinButton
-{
+
+class RenderSkinButton {
public:
/**
* Initialize the class before use. Uses the AssetManager to initialize any
* bitmaps the class may use.
*/
- static void Init(android::AssetManager*, String drawableDirectory);
+ RenderSkinButton(android::AssetManager*, String drawableDirectory);
/**
* Draw the skin to the canvas, using the rectangle for its bounds and the
* State to determine which skin to use, i.e. focused or not focused.
*/
- static void Draw(SkCanvas* , const IntRect& , RenderSkinAndroid::State);
+ void draw(SkCanvas* , const IntRect& , RenderSkinAndroid::State) const;
+private:
+ bool m_decoded;
+ NinePatch m_buttons[4];
};
} // WebCore
diff --git a/WebKit/android/RenderSkinMediaButton.cpp b/WebKit/android/RenderSkinMediaButton.cpp
index 745fa88..090d55e 100644
--- a/WebKit/android/RenderSkinMediaButton.cpp
+++ b/WebKit/android/RenderSkinMediaButton.cpp
@@ -58,8 +58,8 @@ static const PatchData gFiles[] =
{ "spinner_76_inner_holo.png", 0, 0 }, // SPINNER_INNER
{ "ic_media_video_poster.png", 0, 0 }, // VIDEO
{ "btn_media_player_disabled.9.png", 0, 0 }, // BACKGROUND_SLIDER
- { "scrubber_track_holo_dark.9.png", 0, 0 }, // SLIDER_TRACK
- { "scrubber_control_holo.png", 0, 0 } // SLIDER_THUMB
+ { "scrubber_track_holo_dark.9.png", 0, 0 }, // SLIDER_TRACK
+ { "scrubber_control_holo.png", 0, 0 } // SLIDER_THUMB
};
static SkBitmap gButton[sizeof(gFiles)/sizeof(gFiles[0])];
@@ -112,6 +112,7 @@ void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonT
alpha = 190;
SkColor backgroundColor = SkColorSetARGB(alpha, 34, 34, 34);
+ SkColor trackBackgroundColor = SkColorSetARGB(255, 100, 100, 100);
paint.setColor(backgroundColor);
paint.setFlags(SkPaint::kFilterBitmap_Flag);
diff --git a/WebKit/android/RenderSkinNinePatch.cpp b/WebKit/android/RenderSkinNinePatch.cpp
new file mode 100644
index 0000000..0c915c0
--- /dev/null
+++ b/WebKit/android/RenderSkinNinePatch.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+
+#include "RenderSkinNinePatch.h"
+#include "NinePatchPeeker.h"
+#include "SkCanvas.h"
+#include "SkImageDecoder.h"
+#include "SkRect.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+#include <utils/Asset.h>
+#include <utils/AssetManager.h>
+#include <utils/Log.h>
+#include <utils/ResourceTypes.h>
+
+class SkPaint;
+class SkRegion;
+
+using namespace android;
+
+extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
+ const SkBitmap& bitmap, const Res_png_9patch& chunk,
+ const SkPaint* paint, SkRegion** outRegion);
+
+bool RenderSkinNinePatch::decodeAsset(AssetManager* am, const char* filename, NinePatch* ninepatch) {
+ Asset* asset = am->open(filename, android::Asset::ACCESS_BUFFER);
+ if (!asset) {
+ asset = am->openNonAsset(filename, android::Asset::ACCESS_BUFFER);
+ if (!asset) {
+ return false;
+ }
+ }
+
+ SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
+ SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
+ SkStream* stream = new SkMemoryStream(asset->getBuffer(false), asset->getLength());
+ SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
+ if (!decoder) {
+ asset->close();
+ LOGE("RenderSkinNinePatch::Failed to create an image decoder");
+ return false;
+ }
+
+ decoder->setSampleSize(1);
+ decoder->setDitherImage(true);
+ decoder->setPreferQualityOverSpeed(false);
+
+ NinePatchPeeker peeker(decoder);
+
+ SkAutoTDelete<SkImageDecoder> add(decoder);
+
+ decoder->setPeeker(&peeker);
+ if (!decoder->decode(stream, &ninepatch->m_bitmap, prefConfig, mode, true)) {
+ asset->close();
+ LOGE("RenderSkinNinePatch::Failed to decode nine patch asset");
+ return false;
+ }
+
+ asset->close();
+ if (!peeker.fPatchIsValid) {
+ LOGE("RenderSkinNinePatch::Patch data not valid");
+ return false;
+ }
+ void** data = &ninepatch->m_serializedPatchData;
+ *data = malloc(peeker.fPatch->serializedSize());
+ peeker.fPatch->serialize(*data);
+ return true;
+}
+
+void RenderSkinNinePatch::DrawNinePatch(SkCanvas* canvas, const SkRect& bounds,
+ const NinePatch& patch) {
+ Res_png_9patch* data = Res_png_9patch::deserialize(patch.m_serializedPatchData);
+ NinePatch_Draw(canvas, bounds, patch.m_bitmap, *data, 0, 0);
+}
diff --git a/WebKit/android/RenderSkinNinePatch.h b/WebKit/android/RenderSkinNinePatch.h
new file mode 100644
index 0000000..e4db260
--- /dev/null
+++ b/WebKit/android/RenderSkinNinePatch.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RenderSkinNinePatch_h
+#define RenderSkinNinePatch_h
+
+#include "SkBitmap.h"
+#include "utils/Asset.h"
+
+namespace android {
+ class AssetManager;
+}
+
+class SkCanvas;
+class SkRect;
+
+struct NinePatch {
+ SkBitmap m_bitmap;
+ void* m_serializedPatchData;
+ NinePatch() {
+ m_serializedPatchData = 0;
+ }
+ ~NinePatch() {
+ if (m_serializedPatchData)
+ free(m_serializedPatchData);
+ }
+};
+
+class RenderSkinNinePatch {
+public:
+ static bool decodeAsset(android::AssetManager*, const char* fileName, NinePatch*);
+ static void DrawNinePatch(SkCanvas*, const SkRect&, const NinePatch&);
+};
+
+#endif // RenderSkinNinePatch_h
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp
index 7d1adb0..d59a53b 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -334,6 +334,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
mUserAgent = WTF::String();
mUserInitiatedAction = false;
mBlockNetworkLoads = false;
+ m_renderSkins = 0;
}
WebFrame::~WebFrame()
@@ -345,6 +346,7 @@ WebFrame::~WebFrame()
mJavaFrame->mObj = 0;
}
delete mJavaFrame;
+ delete m_renderSkins;
}
WebFrame* WebFrame::getWebFrame(const WebCore::Frame* frame)
@@ -1261,7 +1263,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
// Setup the asset manager.
AssetManager* am = assetManagerForJavaObject(env, jAssetManager);
// Initialize our skinning classes
- WebCore::RenderSkinAndroid::Init(am, directory);
+ webFrame->setRenderSkins(new WebCore::RenderSkinAndroid(am, directory));
}
for (int i = WebCore::PlatformBridge::FileUploadLabel;
i <= WebCore::PlatformBridge::FileUploadNoFileChosenLabel; i++)
diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h
index 25232e4..6522a5f 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/WebKit/android/jni/WebCoreFrameBridge.h
@@ -43,6 +43,7 @@ namespace WebCore {
class Image;
class Page;
class RenderPart;
+ class RenderSkinAndroid;
class ResourceHandle;
class ResourceLoaderAndroid;
class ResourceRequest;
@@ -155,6 +156,8 @@ class WebFrame : public WebCoreRefObject {
bool shouldSaveFormData();
void saveFormData(WebCore::HTMLFormElement*);
+ const WebCore::RenderSkinAndroid* renderSkins() const { return m_renderSkins; }
+ void setRenderSkins(const WebCore::RenderSkinAndroid* skins) { m_renderSkins = skins; }
private:
struct JavaBrowserFrame;
JavaBrowserFrame* mJavaFrame;
@@ -162,6 +165,7 @@ private:
WTF::String mUserAgent;
bool mBlockNetworkLoads;
bool mUserInitiatedAction;
+ const WebCore::RenderSkinAndroid* m_renderSkins;
};
} // namespace android
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 3a156de..053f2a9 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -71,7 +71,9 @@
#include <JNIUtility.h>
#include <JNIHelp.h>
#include <jni.h>
+#include <android_runtime/android_util_AssetManager.h>
#include <ui/KeycodeLabels.h>
+#include <utils/AssetManager.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
@@ -138,7 +140,7 @@ struct JavaGlue {
}
} m_javaGlue;
-WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
+WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir, AssetManager* am) :
m_ring((WebViewCore*) viewImpl)
{
jclass clazz = env->FindClass("android/webkit/WebView");
@@ -190,6 +192,10 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
m_ringAnimationEnd = 0;
m_baseLayer = 0;
m_glDrawFunctor = 0;
+ if (drawableDir.isEmpty())
+ m_buttonSkin = 0;
+ else
+ m_buttonSkin = new RenderSkinButton(am, drawableDir);
#if USE(ACCELERATED_COMPOSITING)
m_glWebViewState = 0;
#endif
@@ -213,6 +219,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
delete m_navPictureUI;
SkSafeUnref(m_baseLayer);
delete m_glDrawFunctor;
+ delete m_buttonSkin;
}
void stopGL()
@@ -279,7 +286,7 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
const CachedNode* cachedCursor = 0;
// Lock the mutex, since we now share with the WebCore thread.
m_viewImpl->gButtonMutex.lock();
- if (m_viewImpl->m_buttons.size()) {
+ if (m_viewImpl->m_buttons.size() && m_buttonSkin) {
// FIXME: In a future change, we should keep track of whether the selection
// has changed to short circuit (note that we would still need to update
// if we received new buttons from the WebCore thread).
@@ -308,7 +315,7 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
state = RenderSkinAndroid::kFocused;
}
}
- ptr->updateFocusState(state);
+ ptr->updateFocusState(state, m_buttonSkin);
}
}
m_viewImpl->gButtonMutex.unlock();
@@ -1463,6 +1470,7 @@ private: // local state for WebView
#if USE(ACCELERATED_COMPOSITING)
GLWebViewState* m_glWebViewState;
#endif
+ const RenderSkinButton* m_buttonSkin;
}; // end of WebView class
@@ -1573,9 +1581,12 @@ static void nativeClearCursor(JNIEnv *env, jobject obj)
view->clearCursor();
}
-static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl)
+static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl, jstring drawableDir,
+ jobject jAssetManager)
{
- WebView* webview = new WebView(env, obj, viewImpl);
+ AssetManager* am = assetManagerForJavaObject(env, jAssetManager);
+ WTF::String dir = jstringToWtfString(env, drawableDir);
+ WebView* webview = new WebView(env, obj, viewImpl, dir, am);
// NEED THIS OR SOMETHING LIKE IT!
//Release(obj);
}
@@ -2489,7 +2500,7 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeCacheHitNodePointer },
{ "nativeClearCursor", "()V",
(void*) nativeClearCursor },
- { "nativeCreate", "(I)V",
+ { "nativeCreate", "(ILjava/lang/String;Landroid/content/res/AssetManager;)V",
(void*) nativeCreate },
{ "nativeCursorFramePointer", "()I",
(void*) nativeCursorFramePointer },