扩展cpp
#include "config.h"
#include "JZFocus.h"#include "WebCoreJni.h"
#include <jni.h>
#include <JNIHelp.h>
#include <JNIUtility.h>
#include <time.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringImpl.h>
#define DEBUG
#ifdef DEBUG
#include <android/log.h>
#undef XLOG
#define XLOG(...) __android_log_print(ANDROID_LOG_INFO, "JZIPanel", __VA_ARGS__)
#else
#undef XLOG
#define XLOG(...)
#endif // DEBUG
namespace WebCore {
JZFocus::JZFocus(Frame* frame)
:m_borders(0)
{
}
JZFocus::~JZFocus()
{
}
void JZFocus::disconnectFrame()
{
}
void JZFocus::setBorders(const int border)
{
m_borders = border;
}
int JZFocus::borders() const
{
return m_borders;
}
}
头文件
#ifndef WebCore_JZFocus_h
#define WebCore_JZFocus_h
#include "PlatformString.h"
#include "Frame.h"
#include <jni.h>
#include <JNIHelp.h>
#include <JNIUtility.h>
#include <wtf/Forward.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/HashMap.h>
#include <wtf/RefPtr.h>
namespace WebCore{
class JZFocus : public RefCounted<JZFocus> {
public:
~JZFocus();
static PassRefPtr<JZFocus> create(Frame* frame)
{
return adoptRef(new JZFocus(frame));
}
void disconnectFrame();
void setBorders(const int width);
int borders() const;
private:
JZFocus(Frame*);
int m_borders;
};
} // namespace WebCore
#endif
对应idl
module core {
interface [OmitConstructor
] JZFocus {
attribute [CustomSetter] long borders;
};
}
ipanel.cpp
#include "config.h"
#include "JZIPanel.h"
#include "JZFocus.h"
#include "WebCoreJni.h"
#include <jni.h>
#include <JNIHelp.h>
#include <JNIUtility.h>
#include <time.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringImpl.h>
#define DEBUG
#ifdef DEBUG
#include <android/log.h>
#undef XLOG
#define XLOG(...) __android_log_print(ANDROID_LOG_INFO, "WebView", __VA_ARGS__)
#else
#undef XLOG
#define XLOG(...)
#endif // DEBUG
bool g_iPanelIsDrawFocusRing = true;
namespace WebCore {
JZIPanel::JZIPanel(Frame* frame)
:m_frame(frame)
,m_focusWidth("3")
{
XLOG("%d, JZIPanel::JZIPanel()", __LINE__);
}
JZIPanel::~JZIPanel()
{
XLOG("%d, JZIPanel::~JZIPanel()", __LINE__);
}
void JZIPanel::disconnectFrame()
{
XLOG("%d, JZIPanel::disconnectFrame()", __LINE__);
if(m_focusWidth == "0")
g_iPanelIsDrawFocusRing = true;
clear();
}
void JZIPanel::clear()
{
if (m_focus)
m_focus->disconnectFrame();
m_focus = 0;
}
JZFocus* JZIPanel::focus() const
{
if (!m_focus)
m_focus = JZFocus::create(m_frame);
return m_focus.get();
}
void JZIPanel::setfocusWidth(const String& width)
{
XLOG("%d, JZIPanel::setfocusWidth() width = %s", __LINE__, width.utf8().data());
m_focusWidth = width;
if(m_focusWidth == "-1" || m_focusWidth == "0")
g_iPanelIsDrawFocusRing = false;
else
g_iPanelIsDrawFocusRing = true;
}
String JZIPanel::focusWidth() const
{
XLOG("%d, JZIPanel::focusWidth() width = %s", __LINE__, m_focusWidth.utf8().data());
return m_focusWidth;
}
void JZIPanel::debug(String& info)
{
}
void JZIPanel::ioctlWrite(String& ctrol, String& detail)
{
globalVarMap.add(ctrol, detail);
}
String JZIPanel::ioctlRead(String& content)
{
XLOG("%d, JZIPanel::ioctlRead() content ---> %s", __LINE__, content.utf8().data());
HashMap<String, String>::iterator m_it = globalVarMap.find(content);
if (m_it != globalVarMap.end()) {
return m_it->second;
}
else {
XLOG("%d, JZIPanel::ioctlRead() Not find !!!", __LINE__);
return String();
}
}
void JZIPanel::setGlobalVar(String& name, String& value)
{
globalVarMap.add(name, value);
}
String JZIPanel::getGlobalVar(String& name)
{
HashMap<String, String>::iterator m_it = globalVarMap.find(name);
if (m_it != globalVarMap.end()) {
return m_it->second;
}
else {
XLOG("%d, JZIPanel::getGlobalVar() Not find !!!", __LINE__);
return String();
}
}
}
/*
* Copyright 2009, 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.
*/
#include "config.h"
#include "RenderThemeAndroid.h"
#include "Color.h"
#include "Element.h"
#include "GraphicsContext.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLSelectElement.h"
#include "Node.h"
#include "PlatformGraphicsContext.h"
#if ENABLE(VIDEO)
#include "RenderMediaControls.h"
#endif
#include "RenderObject.h"
#include "RenderSkinAndroid.h"
#include "RenderSkinMediaButton.h"
#include "RenderSlider.h"
#include "RoundedIntRect.h"
#include "SkCanvas.h"
#include "UserAgentStyleSheets.h"
#include "WebCoreFrameBridge.h"
//#define DEBUG
#ifdef DEBUG
#include <wtf/text/CString.h>
#include <android/log.h>
#undef XLOG
#define XLOG(...) __android_log_print(ANDROID_LOG_INFO, "Render", __VA_ARGS__)
#else
#undef XLOG
#define XLOG(...)
#endif // DEBUG
extern bool g_iPanelIsDrawFocusRing;
namespace WebCore {
// Add padding to the fontSize of ListBoxes to get their maximum sizes.
// Listboxes often have a specified size. Since we change them into
// dropdowns, we want a much smaller height, which encompasses the text.
const int listboxPadding = 5;
// This is the color of selection in a textfield. It was computed from
// frameworks/base/core/res/res/values/colors.xml, which uses #9983CC39
// (decimal a = 153, r = 131, g = 204, b = 57)
// for all four highlighted text values. Blending this with white yields:
// R = (131 * 153 + 255 * (255 - 153)) / 255 -> 180.6
// G = (204 * 153 + 255 * (255 - 153)) / 255 -> 224.4
// B = ( 57 * 153 + 255 * (255 - 153)) / 255 -> 136.2
const RGBA32 selectionColor = makeRGB(181, 224, 136);
// Colors copied from the holo resources
const RGBA32 defaultBgColor = makeRGBA(204, 204, 204, 197);
const RGBA32 defaultBgBright = makeRGBA(213, 213, 213, 221);
const RGBA32 defaultBgDark = makeRGBA(92, 92, 92, 160);
const RGBA32 defaultBgMedium = makeRGBA(132, 132, 132, 111);
const RGBA32 defaultFgColor = makeRGBA(101, 101, 101, 225);
const RGBA32 defaultCheckColor = makeRGBA(0, 153, 204, 255);
const RGBA32 defaultCheckColorShadow = makeRGBA(29, 123, 154, 192);
const RGBA32 disabledBgColor = makeRGBA(205, 205, 205, 107);
const RGBA32 disabledBgBright = makeRGBA(213, 213, 213, 133);
const RGBA32 disabledBgDark = makeRGBA(92, 92, 92, 96);
const RGBA32 disabledBgMedium = makeRGBA(132, 132, 132, 111);
const RGBA32 disabledFgColor = makeRGBA(61, 61, 61, 68);
const RGBA32 disabledCheckColor = makeRGBA(61, 61, 61, 128);
const RGBA32 disabledCheckColorShadow = disabledCheckColor;
const int paddingButton = 2;
const int cornerButton = 2;
// scale factors for various resolutions
const float scaleFactor[RenderSkinAndroid::ResolutionCount] = {
1.0f, // medium res
1.5f, // high res
2.0f // extra high res
};
static android::WebFrame* getWebFrame(const Node* node)
{
if (!node)
return 0;
return android::WebFrame::getWebFrame(node->document()->frame());
}
// Draws a nice, mitered line.
// This is a partial copy from RenderObject::drawLineForBoxSide
static void drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1,
int x2, int y2, BoxSide side, Color color,
int adjacentWidth1, int adjacentWidth2)
{
XLOG("%d, RenderThemeAndroid ---> drawLineForBoxSide()", __LINE__);
static const bool antialias = false;
graphicsContext->setFillColor(color, graphicsContext->fillColorSpace());
if (!adjacentWidth1 && !adjacentWidth2) {
// Turn off antialiasing to match the behavior of drawConvexPolygon();
// this matters for rects in transformed contexts.
bool wasAntialiased = graphicsContext->shouldAntialias();
graphicsContext->setShouldAntialias(antialias);
graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1));
graphicsContext->setShouldAntialias(wasAntialiased);
return;
}
FloatPoint quad[4];
switch (side) {
case BSTop:
quad[0] = FloatPoint(x1 + max(-adjacentWidth1, 0), y1);
quad[1] = FloatPoint(x1 + max(adjacentWidth1, 0), y2);
quad[2] = FloatPoint(x2 - max(adjacentWidth2, 0), y2);
quad[3] = FloatPoint(x2 - max(-adjacentWidth2, 0), y1);
break;
case BSBottom:
quad[0] = FloatPoint(x1 + max(adjacentWidth1, 0), y1);
quad[1] = FloatPoint(x1 + max(-adjacentWidth1, 0), y2);
quad[2] = FloatPoint(x2 - max(-adjacentWidth2, 0), y2);
quad[3] = FloatPoint(x2 - max(adjacentWidth2, 0), y1);
break;
case BSLeft:
quad[0] = FloatPoint(x1, y1 + max(-adjacentWidth1, 0));
quad[1] = FloatPoint(x1, y2 - max(-adjacentWidth2, 0));
quad[2] = FloatPoint(x2, y2 - max(adjacentWidth2, 0));
quad[3] = FloatPoint(x2, y1 + max(adjacentWidth1, 0));
break;
case BSRight:
quad[0] = FloatPoint(x1, y1 + max(adjacentWidth1, 0));
quad[1] = FloatPoint(x1, y2 - max(adjacentWidth2, 0));
quad[2] = FloatPoint(x2, y2 - max(-adjacentWidth2, 0));
quad[3] = FloatPoint(x2, y1 + max(-adjacentWidth1, 0));
break;
}
graphicsContext->drawConvexPolygon(4, quad, antialias);
}
RenderTheme* theme()
{
DEFINE_STATIC_LOCAL(RenderThemeAndroid, androidTheme, ());
return &androidTheme;
}
PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
{
static RenderTheme* rt = RenderThemeAndroid::create().releaseRef();
return rt;
}
PassRefPtr<RenderTheme> RenderThemeAndroid::create()
{
return adoptRef(new RenderThemeAndroid());
}
RenderThemeAndroid::RenderThemeAndroid()
{
}
RenderThemeAndroid::~RenderThemeAndroid()
{
}
void RenderThemeAndroid::close()
{
}
bool RenderThemeAndroid::stateChanged(RenderObject* obj, ControlState state) const
{
if (CheckedState == state) {
obj->repaint();
return true;
}
return false;
}
Color RenderThemeAndroid::platformActiveSelectionBackgroundColor() const
{
return Color(selectionColor);
}
Color RenderThemeAndroid::platformInactiveSelectionBackgroundColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformActiveSelectionForegroundColor() const
{
return Color::black;
}
Color RenderThemeAndroid::platformInactiveSelectionForegroundColor() const
{
return Color::black;
}
Color RenderThemeAndroid::platformTextSearchHighlightColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformActiveListBoxSelectionBackgroundColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformInactiveListBoxSelectionBackgroundColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformActiveListBoxSelectionForegroundColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformInactiveListBoxSelectionForegroundColor() const
{
return Color(Color::transparent);
}
Color RenderThemeAndroid::platformActiveTextSearchHighlightColor() const
{
return Color(0x00, 0x99, 0xcc, 0x99); // HOLO_DARK
}
Color RenderThemeAndroid::platformInactiveTextSearchHighlightColor() const
{
return Color(0x33, 0xb5, 0xe5, 0x66); // HOLO_LIGHT
}
int RenderThemeAndroid::baselinePosition(const RenderObject* obj) const
{
// From the description of this function in RenderTheme.h:
// A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline
// position cannot be determined by examining child content. Checkboxes and radio buttons are examples of
// controls that need to do this.
//
// Our checkboxes and radio buttons need to be offset to line up properly.
return RenderTheme::baselinePosition(obj) - 6;
}
void RenderThemeAndroid::addIntrinsicMargins(RenderStyle* style) const
{
// Cut out the intrinsic margins completely if we end up using a small font size
if (style->fontSize() < 11)
return;
// Intrinsic margin value.
const int m = 2;
// FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
if (style->width().isIntrinsicOrAuto()) {
if (style->marginLeft().quirk())
style->setMarginLeft(Length(m, Fixed));
if (style->marginRight().quirk())
style->setMarginRight(Length(m, Fixed));
}
if (style->height().isAuto()) {
if (style->marginTop().quirk())
style->setMarginTop(Length(m, Fixed));
if (style->marginBottom().quirk())
style->setMarginBottom(Length(m, Fixed));
}
}
bool RenderThemeAndroid::supportsFocus(ControlPart appearance)
{
// jzby add for control if to draw focus
if(!g_iPanelIsDrawFocusRing) {
// true is not draw focus
return true;
}
switch (appearance) {
case PushButtonPart:
case ButtonPart:
case TextFieldPart:
return true;
default:
return false;
}
return false;
}
void RenderThemeAndroid::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const
{
}
bool RenderThemeAndroid::paintCheckbox(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
paintRadio(obj, info, rect);
return false;
}
bool RenderThemeAndroid::paintButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
XLOG("%d, RenderThemeAndroid::paintButton()", __LINE__);
// 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) {
android::WebFrame* webFrame = getWebFrame(node);
if (webFrame) {
GraphicsContext *context = info.context;
IntRect innerrect = IntRect(rect.x() + paddingButton, rect.y() + paddingButton,
rect.width() - 2 * paddingButton, rect.height() - 2 * paddingButton);
IntSize cornerrect = IntSize(cornerButton, cornerButton);
Color bg, bright, dark, medium;
if (formControlElement->isEnabledFormControl()) {
bg = Color(defaultBgColor);
bright = Color(defaultBgBright);
dark = Color(defaultBgDark);
medium = Color(defaultBgMedium);
} else {
bg = Color(disabledBgColor);
bright = Color(disabledBgBright);
dark = Color(disabledBgDark);
medium = Color(disabledBgMedium);
}
context->save();
RoundedIntRect border(rect, cornerrect, cornerrect, cornerrect, cornerrect);
context->addRoundedRectClip(border);
context->setStrokeStyle(NoStroke);
drawLineForBoxSide(context, rect.x(), rect.y(), rect.maxX(), innerrect.y(),
BSTop, bright, paddingButton, paddingButton);
drawLineForBoxSide(context, rect.x(), rect.y(), innerrect.x(), rect.maxY(),
BSLeft, medium, paddingButton, paddingButton);
drawLineForBoxSide(context, innerrect.maxX(), rect.y(), rect.maxX(), rect.maxY(),
BSRight, medium, paddingButton, paddingButton);
drawLineForBoxSide(context, rect.x(), innerrect.maxY(), rect.maxX(), rect.maxY(),
BSBottom, dark, paddingButton, paddingButton);
context->fillRect(innerrect, bg, context->fillColorSpace());
context->restore();
}
}
// We always return false so we do not request to be redrawn.
return false;
}
#if ENABLE(VIDEO)
String RenderThemeAndroid::extraMediaControlsStyleSheet()
{
return String(mediaControlsAndroidUserAgentStyleSheet, sizeof(mediaControlsAndroidUserAgentStyleSheet));
}
bool RenderThemeAndroid::shouldRenderMediaControlPart(ControlPart part, Element* e)
{
HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(e);
switch (part) {
case MediaMuteButtonPart:
return false;
case MediaSeekBackButtonPart:
case MediaSeekForwardButtonPart:
return false;
case MediaRewindButtonPart:
return mediaElement->movieLoadType() != MediaPlayer::LiveStream;
case MediaReturnToRealtimeButtonPart:
return mediaElement->movieLoadType() == MediaPlayer::LiveStream;
case MediaFullscreenButtonPart:
return mediaElement->supportsFullscreen();
case MediaToggleClosedCaptionsButtonPart:
return mediaElement->hasClosedCaptions();
default:
return true;
}
}
bool RenderThemeAndroid::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::FULLSCREEN, translucent);
return false;
}
bool RenderThemeAndroid::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::MUTE, translucent);
return false;
}
bool RenderThemeAndroid::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
if (btn->displayType() == MediaPlayButton)
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::PLAY, translucent);
else
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::PAUSE, translucent);
return false;
}
return true;
}
bool RenderThemeAndroid::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::REWIND, translucent);
return false;
}
bool RenderThemeAndroid::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect, RenderSkinMediaButton::FORWARD, translucent);
return false;
}
bool RenderThemeAndroid::paintMediaControlsBackground(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect,
RenderSkinMediaButton::BACKGROUND_SLIDER,
translucent, false);
return false;
}
bool RenderThemeAndroid::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
IntRect thumb;
if (o && o->isSlider())
thumb = toRenderSlider(o)->thumbRect();
paintInfo.context->platformContext()->drawMediaButton(rect,
RenderSkinMediaButton::SLIDER_TRACK, translucent, true, thumb);
return false;
}
bool RenderThemeAndroid::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
bool translucent = false;
if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
translucent = true;
paintInfo.context->platformContext()->drawMediaButton(rect,
RenderSkinMediaButton::SLIDER_THUMB,
translucent, false);
return false;
}
void RenderThemeAndroid::adjustSliderThumbSize(RenderObject* o) const
{
static const int sliderThumbWidth = RenderSkinMediaButton::sliderThumbWidth();
static const int sliderThumbHeight = RenderSkinMediaButton::sliderThumbHeight();
o->style()->setWidth(Length(sliderThumbWidth, Fixed));
o->style()->setHeight(Length(sliderThumbHeight, Fixed));
}
#endif
bool RenderThemeAndroid::paintRadio(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
Node* node = obj->node();
Element* element = static_cast<Element*>(node);
if (element) {
InputElement* input = element->toInputElement();
GraphicsContext* context = info.context;
context->save();
Color borderColor = defaultFgColor;
Color checkColor = defaultCheckColor;
Color checkColorShadow = defaultCheckColorShadow;
if (!element->isEnabledFormControl()) {
borderColor = disabledFgColor;
checkColor = disabledCheckColor;
checkColorShadow = disabledCheckColorShadow;
}
IntRect borderRect = rect;
borderRect.inflate(-3);
const float cx = borderRect.center().x();
const float cy = borderRect.center().y() - 1;
context->setStrokeStyle(SolidStroke);
context->setStrokeColor(borderColor, context->strokeColorSpace());
context->setStrokeThickness(1);
context->setFillColor(Color::transparent, context->fillColorSpace());
context->setShadow(FloatSize(), 1.0f, borderColor, context->fillColorSpace());
if (input->isCheckbox()) {
if (input->isChecked()) {
Path clip;
clip.moveTo(FloatPoint(cx, cy - 1));
clip.addLineTo(FloatPoint(rect.maxX() - 3, rect.y() + 1));
clip.addLineTo(FloatPoint(rect.maxX(), rect.y() + 4));
clip.addLineTo(FloatPoint(cx, cy + 5));
clip.closeSubpath();
context->save();
context->clipOut(clip);
}
context->drawRect(borderRect);
if (input->isChecked())
context->restore();
} else
context->drawEllipse(borderRect);
if (input->isChecked()) {
context->setFillColor(checkColor, context->fillColorSpace());
context->setStrokeColor(Color::transparent, context->strokeColorSpace());
context->setShadow(FloatSize(), 2, checkColorShadow, context->fillColorSpace());
if (input->isCheckbox()) {
Path checkmark;
checkmark.moveTo(FloatPoint(cx, cy));
checkmark.addLineTo(FloatPoint(rect.maxX() - 2, rect.y() + 1));
checkmark.addLineTo(FloatPoint(rect.maxX(), rect.y() + 3));
checkmark.addLineTo(FloatPoint(cx, cy + 4));
checkmark.addLineTo(FloatPoint(cx - 4, cy));
checkmark.addLineTo(FloatPoint(cx - 2, cy - 2));
checkmark.closeSubpath();
context->fillPath(checkmark);
} else {
borderRect.inflate(-3);
context->drawEllipse(borderRect);
}
}
context->restore();
}
return false;
}
void RenderThemeAndroid::setCheckboxSize(RenderStyle* style) const
{
style->setWidth(Length(19, Fixed));
style->setHeight(Length(19, Fixed));
}
void RenderThemeAndroid::setRadioSize(RenderStyle* style) const
{
// This is the same as checkboxes.
setCheckboxSize(style);
}
void RenderThemeAndroid::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const
{
addIntrinsicMargins(style);
}
bool RenderThemeAndroid::paintTextField(RenderObject*, const PaintInfo&, const IntRect&)
{
return true;
}
void RenderThemeAndroid::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const
{
addIntrinsicMargins(style);
}
bool RenderThemeAndroid::paintTextArea(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
if (obj->isMenuList())
paintCombo(obj, info, rect);
return true;
}
void RenderThemeAndroid::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
addIntrinsicMargins(style);
}
bool RenderThemeAndroid::paintSearchField(RenderObject*, const PaintInfo&, const IntRect&)
{
return true;
}
static void adjustMenuListStyleCommon(RenderStyle* style)
{
// Added to make room for our arrow and make the touch target less cramped.
const int padding = (int)(scaleFactor[RenderSkinAndroid::DrawableResolution()] + 0.5f);
style->setPaddingLeft(Length(padding,Fixed));
style->setPaddingTop(Length(padding, Fixed));
style->setPaddingBottom(Length(padding, Fixed));
// allocate height as arrow size
int arrow = std::max(18, style->fontMetrics().height() + 2 * padding);
style->setPaddingRight(Length(arrow, Fixed));
style->setMinHeight(Length(arrow, Fixed));
style->setHeight(Length(arrow, Fixed));
}
void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
{
adjustMenuListButtonStyle(0, style, 0);
}
void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
{
adjustMenuListStyleCommon(style);
addIntrinsicMargins(style);
}
bool RenderThemeAndroid::paintCombo(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
if (obj->style() && !obj->style()->visitedDependentColor(CSSPropertyBackgroundColor).alpha())
return true;
Node* node = obj->node();
Element* element = static_cast<Element*>(node);
if (element) {
InputElement* input = element->toInputElement();
GraphicsContext* context = info.context;
context->save();
if (!element->isEnabledFormControl())
context->setAlpha(0.5f);
IntRect bounds = IntRect(rect.x(), rect.y(), rect.width(), rect.height());
// paint bg color
RenderStyle* style = obj->style();
context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor),
context->fillColorSpace());
context->fillRect(FloatRect(bounds));
// copied form the original RenderSkinCombo:
// If this is an appearance where RenderTheme::paint returns true
// without doing anything, this means that
// RenderBox::PaintBoxDecorationWithSize will end up painting the
// border, so we shouldn't paint a border here.
if (style->appearance() != MenulistButtonPart &&
style->appearance() != ListboxPart &&
style->appearance() != TextFieldPart &&
style->appearance() != TextAreaPart) {
const int arrowSize = bounds.height();
// dropdown button bg
context->setFillColor(Color(defaultBgColor), context->fillColorSpace());
context->fillRect(FloatRect(bounds.maxX() - arrowSize + 0.5f, bounds.y() + .5f,
arrowSize - 1, bounds.height() - 1));
// outline
context->setStrokeStyle(SolidStroke);
context->setStrokeThickness(1.0f);
context->setStrokeColor(Color(defaultBgDark), context->strokeColorSpace());
context->strokeRect(bounds, 1.0f);
// arrow
context->setFillColor(Color(defaultFgColor), context->fillColorSpace());
Path tri = Path();
tri.clear();
const float aw = arrowSize - 10;
FloatPoint br = FloatPoint(bounds.maxX() - 4, bounds.maxY() - 4);
tri.moveTo(br);
tri.addLineTo(FloatPoint(br.x() - aw, br.y()));
tri.addLineTo(FloatPoint(br.x(), br.y() - aw));
context->fillPath(tri);
}
context->restore();
}
return false;
}
bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
return paintCombo(obj, info, rect);
}
void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*,
RenderStyle* style, Element*) const
{
// Copied from RenderThemeSafari.
const float baseFontSize = 11.0f;
const int baseBorderRadius = 5;
float fontScale = style->fontSize() / baseFontSize;
style->resetPadding();
style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
const int minHeight = 15;
style->setMinHeight(Length(minHeight, Fixed));
style->setLineHeight(RenderStyle::initialLineHeight());
// Found these padding numbers by trial and error.
const int padding = 4;
style->setPaddingTop(Length(padding, Fixed));
style->setPaddingLeft(Length(padding, Fixed));
adjustMenuListStyleCommon(style);
}
bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
{
return paintCombo(obj, info, rect);
}
bool RenderThemeAndroid::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
static const bool translucent = true;
i.context->platformContext()->drawMediaButton(r,
RenderSkinMediaButton::SLIDER_TRACK,
translucent, false);
return false;
}
bool RenderThemeAndroid::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
static const bool translucent = true;
i.context->platformContext()->drawMediaButton(r,
RenderSkinMediaButton::SLIDER_THUMB,
translucent, false);
return false;
}
Color RenderThemeAndroid::platformFocusRingColor() const
{
//static Color focusRingColor(0x33, 0xB5, 0xE5, 0x66);
// jzby here can change focus color
static Color focusRingColor(0xFF, 0xFF, 0x00, 0xFF);
return focusRingColor;
}
bool RenderThemeAndroid::supportsFocusRing(const RenderStyle* style) const
{
// jzby add for draw focus at core
return supportsFocus(style->appearance());
// Draw the focus ring ourselves unless it is a text area (webkit does borders better)
if (!style || !style->hasAppearance())
return true;
return style->appearance() != TextFieldPart && style->appearance() != TextAreaPart;
}
} // namespace WebCore