# 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)
#include "RenderSkinRadio.h"
#include "SkCanvas.h"
#include "UserAgentStyleSheets.h"
+#include "WebCoreFrameBridge.h"
namespace WebCore {
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, ());
// 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);
// 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;
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:
android/RenderSkinButton.cpp \
android/RenderSkinCombo.cpp \
android/RenderSkinMediaButton.cpp \
+ android/RenderSkinNinePatch.cpp \
android/RenderSkinRadio.cpp \
android/TimeCounter.cpp \
\
#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);
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,
* 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
*/
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
#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;
}
}
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;
}
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
#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
{ "ic_media_ff.png", 0, 0 }, // FORWARD
{ "ic_media_fullscreen.png", 0, 0 }, // FULLSCREEN
{ "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
+ { "btn_media_player_pressed.9.png", 0, 0 }, // SLIDER_TRACK
+ { "btn_media_player.9.png", 0, 0 } // SLIDER_THUMB
};
static SkBitmap gButton[sizeof(gFiles)/sizeof(gFiles[0])];
return;
}
- bool drawsNinePatch = false;
+ bool drawsNinePatch = true;
bool drawsImage = true;
- bool drawsBackgroundColor = true;
+ bool drawsBackgroundColor = false;
int ninePatchIndex = 0;
int imageIndex = 0;
SkRect bounds(r);
SkScalar imageMargin = 8;
SkPaint paint;
-
- int alpha = 255;
- if (translucent)
- alpha = 190;
-
- SkColor backgroundColor = SkColorSetARGB(alpha, 34, 34, 34);
- paint.setColor(backgroundColor);
+ SkColor backgroundColor = SkColorSetARGB(255, 200, 200, 200);
+ SkColor trackBackgroundColor = SkColorSetARGB(255, 100, 100, 100);
switch (buttonType) {
case PAUSE:
case FULLSCREEN:
{
imageIndex = buttonType + 1;
+ drawsBackgroundColor = true;
paint.setColor(backgroundColor);
break;
}
{
drawsBackgroundColor = false;
drawsImage = false;
+ drawsNinePatch = false;
+ drawsBackgroundColor = true;
+ paint.setColor(backgroundColor);
break;
}
case SLIDER_TRACK:
{
- drawsNinePatch = true;
drawsImage = false;
- ninePatchIndex = buttonType + 1;
+ drawsNinePatch = false;
+ drawsBackgroundColor = true;
+ paint.setColor(trackBackgroundColor);
+ bounds.fTop += 8;
+ bounds.fBottom -= 8;
break;
}
case SLIDER_THUMB:
{
- drawsBackgroundColor = false;
- imageMargin = 0;
- imageIndex = buttonType + 1;
+ drawsImage = false;
+ ninePatchIndex = buttonType + 1;
break;
}
default:
- return;
+ drawsImage = false;
+ drawsNinePatch = false;
}
if (drawsBackgroundColor) {
SkIRect margin;
margin.set(marginValue, marginValue, marginValue, marginValue);
- SkNinePatch::DrawNine(canvas, bounds, gButton[ninePatchIndex], margin);
+ SkNinePatch::DrawNine(canvas, bounds, gButton[0], margin);
}
if (drawsImage) {
/**
* Slider dimensions
*/
- static int sliderThumbWidth() { return 32; }
- static int sliderThumbHeight() { return 32; }
+ static int sliderThumbWidth() { return 10; }
+ static int sliderThumbHeight() { return 30; }
};
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
mUserAgent = WTF::String();
mUserInitiatedAction = false;
mBlockNetworkLoads = false;
+ m_renderSkins = 0;
}
WebFrame::~WebFrame()
mJavaFrame->mObj = 0;
}
delete mJavaFrame;
+ delete m_renderSkins;
}
WebFrame* WebFrame::getWebFrame(const WebCore::Frame* frame)
// 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++)
class Image;
class Page;
class RenderPart;
+ class RenderSkinAndroid;
class ResourceHandle;
class ResourceLoaderAndroid;
class ResourceRequest;
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;
WTF::String mUserAgent;
bool mBlockNetworkLoads;
bool mUserInitiatedAction;
+ const WebCore::RenderSkinAndroid* m_renderSkins;
};
} // namespace android
#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>
}
} 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");
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
delete m_navPictureUI;
SkSafeUnref(m_baseLayer);
delete m_glDrawFunctor;
+ delete m_buttonSkin;
}
void stopGL()
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).
state = RenderSkinAndroid::kFocused;
}
}
- ptr->updateFocusState(state);
+ ptr->updateFocusState(state, m_buttonSkin);
}
}
m_viewImpl->gButtonMutex.unlock();
#if USE(ACCELERATED_COMPOSITING)
GLWebViewState* m_glWebViewState;
#endif
+ const RenderSkinButton* m_buttonSkin;
}; // end of WebView class
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);
}
(void*) nativeCacheHitNodePointer },
{ "nativeClearCursor", "()V",
(void*) nativeClearCursor },
- { "nativeCreate", "(I)V",
+ { "nativeCreate", "(ILjava/lang/String;Landroid/content/res/AssetManager;)V",
(void*) nativeCreate },
{ "nativeCursorFramePointer", "()I",
(void*) nativeCursorFramePointer },