more layers extracted from webkit

git-svn-id: http://skia.googlecode.com/svn/trunk@503 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2010-02-19 21:41:30 +00:00
parent 81dc331e65
commit da6fb3246a
4 changed files with 186 additions and 200 deletions

View File

@ -40,12 +40,11 @@ struct SkIRect {
*/
int height() const { return fBottom - fTop; }
friend int operator==(const SkIRect& a, const SkIRect& b)
{
friend int operator==(const SkIRect& a, const SkIRect& b) {
return !memcmp(&a, &b, sizeof(a));
}
friend int operator!=(const SkIRect& a, const SkIRect& b)
{
friend int operator!=(const SkIRect& a, const SkIRect& b) {
return memcmp(&a, &b, sizeof(a));
}
@ -58,8 +57,7 @@ struct SkIRect {
*/
void setEmpty() { memset(this, 0, sizeof(*this)); }
void set(int32_t left, int32_t top, int32_t right, int32_t bottom)
{
void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {
fLeft = left;
fTop = top;
fRight = right;
@ -69,32 +67,34 @@ struct SkIRect {
/** Offset set the rectangle by adding dx to its left and right,
and adding dy to its top and bottom.
*/
void offset(int32_t dx, int32_t dy)
{
void offset(int32_t dx, int32_t dy) {
fLeft += dx;
fTop += dy;
fRight += dx;
fBottom += dy;
}
void offset(const SkIPoint& delta) {
this->offset(delta.fX, delta.fY);
}
/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
making the rectangle narrower. If dx is negative, then the sides are moved outwards,
making the rectangle wider. The same hods true for dy and the top and bottom.
*/
void inset(int32_t dx, int32_t dy)
{
void inset(int32_t dx, int32_t dy) {
fLeft += dx;
fTop += dy;
fRight -= dx;
fBottom -= dy;
}
/** Returns true if (x,y) is inside the rectangle and the rectangle is not
empty. The left and top are considered to be inside, while the right
and bottom are not. Thus for the rectangle (0, 0, 5, 10), the
points (0,0) and (0,9) are inside, while (-1,0) and (5,9) are not.
*/
bool contains(int32_t x, int32_t y) const
{
bool contains(int32_t x, int32_t y) const {
return (unsigned)(x - fLeft) < (unsigned)(fRight - fLeft) &&
(unsigned)(y - fTop) < (unsigned)(fBottom - fTop);
}
@ -102,8 +102,7 @@ struct SkIRect {
/** Returns true if the 4 specified sides of a rectangle are inside or equal to this rectangle.
If either rectangle is empty, contains() returns false.
*/
bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const
{
bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {
return left < right && top < bottom && !this->isEmpty() && // check for empties
fLeft <= left && fTop <= top &&
fRight >= right && fBottom >= bottom;
@ -111,8 +110,7 @@ struct SkIRect {
/** Returns true if the specified rectangle r is inside or equal to this rectangle.
*/
bool contains(const SkIRect& r) const
{
bool contains(const SkIRect& r) const {
return !r.isEmpty() && !this->isEmpty() && // check for empties
fLeft <= r.fLeft && fTop <= r.fTop &&
fRight >= r.fRight && fBottom >= r.fBottom;
@ -125,8 +123,7 @@ struct SkIRect {
specified rectangles are non-empty.
*/
bool containsNoEmptyCheck(int32_t left, int32_t top,
int32_t right, int32_t bottom) const
{
int32_t right, int32_t bottom) const {
SkASSERT(fLeft < fRight && fTop < fBottom);
SkASSERT(left < right && top < bottom);
@ -138,8 +135,7 @@ struct SkIRect {
intersection, otherwise return false and do not change this rectangle.
If either rectangle is empty, do nothing and return false.
*/
bool intersect(const SkIRect& r)
{
bool intersect(const SkIRect& r) {
SkASSERT(&r);
return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom);
}
@ -148,14 +144,12 @@ struct SkIRect {
that intersection, otherwise return false and do not change this
rectangle. If either rectangle is empty, do nothing and return false.
*/
bool intersect(const SkIRect& a, const SkIRect& b)
{
bool intersect(const SkIRect& a, const SkIRect& b) {
SkASSERT(&a && &b);
if (!a.isEmpty() && !b.isEmpty() &&
a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom)
{
a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom) {
fLeft = SkMax32(a.fLeft, b.fLeft);
fTop = SkMax32(a.fTop, b.fTop);
fRight = SkMin32(a.fRight, b.fRight);
@ -171,14 +165,12 @@ struct SkIRect {
If either is, then the return result is undefined. In the debug build,
we assert that both rectangles are non-empty.
*/
bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b)
{
bool intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {
SkASSERT(&a && &b);
SkASSERT(!a.isEmpty() && !b.isEmpty());
if (a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom)
{
a.fTop < b.fBottom && b.fTop < a.fBottom) {
fLeft = SkMax32(a.fLeft, b.fLeft);
fTop = SkMax32(a.fTop, b.fTop);
fRight = SkMin32(a.fRight, b.fRight);
@ -193,11 +185,9 @@ struct SkIRect {
otherwise return false and do not change this rectangle.
If either rectangle is empty, do nothing and return false.
*/
bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom)
{
bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
if (left < right && top < bottom && !this->isEmpty() &&
fLeft < right && left < fRight && fTop < bottom && top < fBottom)
{
fLeft < right && left < fRight && fTop < bottom && top < fBottom) {
if (fLeft < left) fLeft = left;
if (fTop < top) fTop = top;
if (fRight > right) fRight = right;
@ -209,8 +199,7 @@ struct SkIRect {
/** Returns true if a and b are not empty, and they intersect
*/
static bool Intersects(const SkIRect& a, const SkIRect& b)
{
static bool Intersects(const SkIRect& a, const SkIRect& b) {
return !a.isEmpty() && !b.isEmpty() && // check for empties
a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom;
@ -226,8 +215,7 @@ struct SkIRect {
If this rectangle is empty, just set it to the specified rectangle. If the specified
rectangle is empty, do nothing.
*/
void join(const SkIRect& r)
{
void join(const SkIRect& r) {
this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
}
@ -252,12 +240,11 @@ struct SkRect {
SkScalar centerX() const { return SkScalarHalf(fLeft + fRight); }
SkScalar centerY() const { return SkScalarHalf(fTop + fBottom); }
friend int operator==(const SkRect& a, const SkRect& b)
{
friend int operator==(const SkRect& a, const SkRect& b) {
return !memcmp(&a, &b, sizeof(a));
}
friend int operator!=(const SkRect& a, const SkRect& b)
{
friend int operator!=(const SkRect& a, const SkRect& b) {
return memcmp(&a, &b, sizeof(a));
}
@ -269,16 +256,14 @@ struct SkRect {
*/
void setEmpty() { memset(this, 0, sizeof(*this)); }
void set(const SkIRect& src)
{
void set(const SkIRect& src) {
fLeft = SkIntToScalar(src.fLeft);
fTop = SkIntToScalar(src.fTop);
fRight = SkIntToScalar(src.fRight);
fBottom = SkIntToScalar(src.fBottom);
}
void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom)
{
void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {
fLeft = left;
fTop = top;
fRight = right;
@ -304,20 +289,22 @@ struct SkRect {
/** Offset set the rectangle by adding dx to its left and right,
and adding dy to its top and bottom.
*/
void offset(SkScalar dx, SkScalar dy)
{
void offset(SkScalar dx, SkScalar dy) {
fLeft += dx;
fTop += dy;
fRight += dx;
fBottom += dy;
}
void offset(const SkPoint& delta) {
this->offset(delta.fX, delta.fY);
}
/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
making the rectangle narrower. If dx is negative, then the sides are moved outwards,
making the rectangle wider. The same hods true for dy and the top and bottom.
*/
void inset(SkScalar dx, SkScalar dy)
{
void inset(SkScalar dx, SkScalar dy) {
fLeft += dx;
fTop += dy;
fRight -= dx;
@ -340,8 +327,7 @@ struct SkRect {
/** Return true if this rectangle is not empty, and the specified sides of
a rectangle are not empty, and they intersect.
*/
bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const
{
bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {
return // first check that both are not empty
left < right && top < bottom &&
fLeft < fRight && fTop < fBottom &&
@ -352,8 +338,7 @@ struct SkRect {
/** Return true if rectangles a and b are not empty and intersect.
*/
static bool Intersects(const SkRect& a, const SkRect& b)
{
static bool Intersects(const SkRect& a, const SkRect& b) {
return !a.isEmpty() && !b.isEmpty() && // check for empties
a.fLeft < b.fRight && b.fLeft < a.fRight &&
a.fTop < b.fBottom && b.fTop < a.fBottom;
@ -369,8 +354,7 @@ struct SkRect {
If this rectangle is empty, just set it to the specified rectangle. If the specified
rectangle is empty, do nothing.
*/
void join(const SkRect& r)
{
void join(const SkRect& r) {
this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);
}
@ -380,8 +364,7 @@ struct SkRect {
while (-1,0) and (5,9) are not.
If this rectangle is empty, return false.
*/
bool contains(const SkPoint& p) const
{
bool contains(const SkPoint& p) const {
return !this->isEmpty() &&
fLeft <= p.fX && p.fX < fRight &&
fTop <= p.fY && p.fY < fBottom;
@ -393,8 +376,7 @@ struct SkRect {
while (-1,0) and (5,9) are not.
If this rectangle is empty, return false.
*/
bool contains(SkScalar x, SkScalar y) const
{
bool contains(SkScalar x, SkScalar y) const {
return !this->isEmpty() &&
fLeft <= x && x < fRight &&
fTop <= y && y < fBottom;
@ -403,8 +385,7 @@ struct SkRect {
/** Return true if this rectangle contains r.
If either rectangle is empty, return false.
*/
bool contains(const SkRect& r) const
{
bool contains(const SkRect& r) const {
return !r.isEmpty() && !this->isEmpty() && // check for empties
fLeft <= r.fLeft && fTop <= r.fTop &&
fRight >= r.fRight && fBottom >= r.fBottom;
@ -413,8 +394,7 @@ struct SkRect {
/** Set the dst integer rectangle by rounding this rectangle's coordinates
to their nearest integer values.
*/
void round(SkIRect* dst) const
{
void round(SkIRect* dst) const {
SkASSERT(dst);
dst->set(SkScalarRound(fLeft), SkScalarRound(fTop), SkScalarRound(fRight), SkScalarRound(fBottom));
}
@ -422,8 +402,7 @@ struct SkRect {
/** Set the dst integer rectangle by rounding "out" this rectangle, choosing the floor of top and left,
and the ceiling of right and bototm.
*/
void roundOut(SkIRect* dst) const
{
void roundOut(SkIRect* dst) const {
SkASSERT(dst);
dst->set(SkScalarFloor(fLeft), SkScalarFloor(fTop), SkScalarCeil(fRight), SkScalarCeil(fBottom));
}

View File

@ -26,33 +26,6 @@
#include "SkSize.h"
class SkCanvas;
class SkPicture;
struct SkLength {
enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };
SkLengthType type;
SkScalar value;
SkLength() {
type = Undefined;
value = 0;
}
bool defined() const {
if (type == Undefined)
return false;
return true;
}
float calcFloatValue(float max) const {
switch (type) {
case Percent:
return (max * value) / 100.0f;
case Fixed:
return value;
default:
return value;
}
}
};
class SkLayer : public SkRefCnt {
@ -61,48 +34,21 @@ public:
SkLayer(const SkLayer&);
virtual ~SkLayer();
// deprecated
void setTranslation(SkScalar x, SkScalar y) { m_translation.set(x, y); }
void setRotation(SkScalar a) { m_angleTransform = a; m_doRotation = true; }
void setScale(SkScalar x, SkScalar y) { m_scale.set(x, y); }
SkPoint position() const { return m_position; }
SkPoint translation() const { return m_translation; }
SkSize size() const { return m_size; }
SkRect bounds() const {
SkRect rect;
rect.set(m_position.fX, m_position.fY,
m_position.fX + m_size.width(),
m_position.fY + m_size.height());
rect.offset(m_translation.fX, m_translation.fY);
return rect;
}
const SkSize& getSize() const { return m_size; }
void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
SkScalar getOpacity() const { return m_opacity; }
void setOpacity(SkScalar opacity) { m_opacity = opacity; }
const SkSize& getSize() const { return m_size; }
const SkPoint& getPosition() const { return m_position; }
void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
const SkPoint& getAnchorPoint() const { return m_anchorPoint; }
void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); }
virtual void setBackgroundColor(SkColor color) { m_backgroundColor = color; m_backgroundColorSet = true; }
void setFixedPosition(SkLength left, SkLength top, SkLength right, SkLength bottom) {
m_fixedLeft = left;
m_fixedTop = top;
m_fixedRight = right;
m_fixedBottom = bottom;
m_isFixed = true;
}
const SkMatrix& getMatrix() const { return fMatrix; }
void setMatrix(const SkMatrix&);
const SkMatrix& getChildrenMatrix() const { return fChildrenMatrix; }
SkScalar getWidth() const { return m_size.width(); }
SkScalar getHeight() const { return m_size.height(); }
void setOpacity(SkScalar opacity) { m_opacity = opacity; }
void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); }
void setMatrix(const SkMatrix&);
void setChildrenMatrix(const SkMatrix&);
// children
@ -114,40 +60,22 @@ public:
// paint method
virtual void draw(SkCanvas*, SkScalar opacity, const SkRect* viewPort);
void draw(SkCanvas*, SkScalar opacity);
void draw(SkCanvas* canvas) {
this->draw(canvas, SK_Scalar1);
}
protected:
virtual void onSetupCanvas(SkCanvas*, SkScalar opacity, const SkRect*);
virtual void onDraw(SkCanvas*, SkScalar opacity, const SkRect* viewPort);
virtual void onDraw(SkCanvas*, SkScalar opacity);
private:
SkScalar m_opacity;
SkSize m_size;
SkPoint m_position;
SkPoint m_anchorPoint;
SkMatrix fMatrix;
SkMatrix fChildrenMatrix;
public:
bool m_doRotation;
bool m_isFixed;
bool m_backgroundColorSet;
// layers properties
SkScalar m_angleTransform;
SkScalar m_opacity;
SkSize m_size;
SkPoint m_position;
SkPoint m_translation;
SkPoint m_anchorPoint;
SkPoint m_scale;
SkLength m_fixedLeft;
SkLength m_fixedTop;
SkLength m_fixedRight;
SkLength m_fixedBottom;
SkColor m_backgroundColor;
SkTDArray<SkLayer*> m_children;
};

View File

@ -0,0 +1,92 @@
#include "SampleCode.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkView.h"
#include "SkLayer.h"
///////////////////////////////////////////////////////////////////////////////
class TestLayer : public SkLayer {
public:
TestLayer(SkColor c) : fColor(c) {}
protected:
virtual void onDraw(SkCanvas* canvas, SkScalar opacity) {
SkRect r;
r.set(0, 0, this->getWidth(), this->getHeight());
SkPaint paint;
paint.setColor(fColor);
paint.setAlpha(SkScalarRound(opacity * 255));
canvas->drawRect(r, paint);
}
private:
SkColor fColor;
};
class SkLayerView : public SkView {
private:
SkLayer* fRootLayer;
public:
SkLayerView() {
static const int W = 640;
static const int H = 480;
static const struct {
int fWidth;
int fHeight;
SkColor fColor;
int fPosX;
int fPosY;
} gData[] = {
{ 120, 80, SK_ColorRED, 0, 0 },
{ 120, 80, SK_ColorGREEN, W - 120, 0 },
{ 120, 80, SK_ColorBLUE, 0, H - 80 },
{ 120, 80, SK_ColorMAGENTA, W - 120, H - 80 },
};
fRootLayer = new SkLayer;
fRootLayer->setSize(W, H);
for (size_t i = 0; i < SK_ARRAY_COUNT(gData); i++) {
SkLayer* child = new TestLayer(gData[i].fColor);
child->setSize(gData[i].fWidth, gData[i].fHeight);
child->setPosition(gData[i].fPosX, gData[i].fPosY);
fRootLayer->addChild(child)->unref();
}
}
virtual ~SkLayerView() {
SkSafeUnref(fRootLayer);
}
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "SkLayer");
return true;
}
return this->INHERITED::onQuery(evt);
}
void drawBG(SkCanvas* canvas) {
canvas->drawColor(0xFFDDDDDD);
fRootLayer->draw(canvas);
}
virtual void onDraw(SkCanvas* canvas) {
this->drawBG(canvas);
}
private:
typedef SkView INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() { return new SkLayerView; }
static SkViewRegister reg(MyFactory);

View File

@ -2,44 +2,20 @@
#include "SkCanvas.h"
SkLayer::SkLayer() {
m_doRotation = false;
m_isFixed = false;
m_backgroundColorSet = false;
m_angleTransform = 0;
m_opacity = 1;
m_size.set(0, 0);
m_position.set(0, 0);
m_translation.set(0, 0);
m_anchorPoint.set(0.5, 0.5);
m_scale.set(1, 1);
m_backgroundColor = 0;
fMatrix.reset();
fChildrenMatrix.reset();
}
SkLayer::SkLayer(const SkLayer& src) {
m_doRotation = src.m_doRotation;
m_isFixed = src.m_isFixed;
m_backgroundColorSet = src.m_backgroundColorSet;
m_angleTransform = src.m_angleTransform;
m_opacity = src.m_opacity;
m_size = src.m_size;
m_position = src.m_position;
m_translation = src.m_translation;
m_anchorPoint = src.m_anchorPoint;
m_scale = src.m_scale;
m_fixedLeft = src.m_fixedLeft;
m_fixedTop = src.m_fixedTop;
m_fixedRight = src.m_fixedRight;
m_fixedBottom = src.m_fixedBottom;
m_backgroundColor = src.m_backgroundColor;
fMatrix = src.fMatrix;
fChildrenMatrix = src.fChildrenMatrix;
@ -83,43 +59,54 @@ void SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
///////////////////////////////////////////////////////////////////////////////
void SkLayer::onSetupCanvas(SkCanvas* canvas, SkScalar, const SkRect*) {
SkScalar tx = m_position.fX;
SkScalar ty = m_position.fY;
canvas->translate(tx, ty);
// now apply our matrix about the anchorPoint
tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
canvas->translate(tx, ty);
canvas->concat(this->getMatrix());
canvas->translate(-tx, -ty);
void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
// SkDebugf("----- no onDraw for %p\n", this);
}
void SkLayer::onDraw(SkCanvas*, SkScalar opacity, const SkRect* viewport) {}
#include "SkString.h"
void SkLayer::draw(SkCanvas* canvas, SkScalar opacity, const SkRect* viewport) {
void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
#if 0
SkDebugf("--- drawlayer %p anchor [%g %g] scale [%g %g]\n", this, m_anchorPoint.fX, m_anchorPoint.fY,
m_scale.fX, m_scale.fY);
SkString str1, str2;
// this->getMatrix().toDumpString(&str1);
// this->getChildrenMatrix().toDumpString(&str2);
SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n",
this, opacity * this->getOpacity(), m_size.width(), m_size.height(),
m_position.fX, m_position.fY, str1.c_str(), str2.c_str());
#endif
opacity = SkScalarMul(opacity, this->getOpacity());
if (opacity <= 0 || this->getSize().isEmpty()) {
#if 0
SkDebugf("---- abort drawing %p opacity %g size [%g %g]\n",
this, opacity, m_size.width(), m_size.height());
#endif
return;
}
SkAutoCanvasRestore acr(canvas, false);
canvas->save(SkCanvas::kMatrix_SaveFlag);
SkAutoCanvasRestore acr(canvas, true);
this->onSetupCanvas(canvas, opacity, viewport);
this->onDraw(canvas, opacity, viewport);
// update the matrix
{
SkScalar tx = m_position.fX;
SkScalar ty = m_position.fY;
canvas->translate(tx, ty);
// now apply our matrix about the anchorPoint
tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
canvas->translate(tx, ty);
canvas->concat(this->getMatrix());
canvas->translate(-tx, -ty);
}
this->onDraw(canvas, opacity);
int count = this->countChildren();
if (count > 0) {
canvas->concat(this->getChildrenMatrix());
for (int i = 0; i < count; i++) {
this->getChild(i)->draw(canvas, opacity, viewport);
this->getChild(i)->draw(canvas, opacity);
}
}
}