diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:09:42 +0000 |
commit | ae2c20f398933a9e86c387dcc465ec0f71065ffc (patch) | |
tree | de668b1411e2ee0b4e49b6d8f8b68183134ac990 /skia/views/SkEvent.cpp | |
parent | 09911bf300f1a419907a9412154760efd0b7abc3 (diff) | |
download | chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.zip chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.gz chromium_src-ae2c20f398933a9e86c387dcc465ec0f71065ffc.tar.bz2 |
Add skia to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/views/SkEvent.cpp')
-rw-r--r-- | skia/views/SkEvent.cpp | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/skia/views/SkEvent.cpp b/skia/views/SkEvent.cpp new file mode 100644 index 0000000..7d00862 --- /dev/null +++ b/skia/views/SkEvent.cpp @@ -0,0 +1,565 @@ +/* libs/graphics/views/SkEvent.cpp +** +** Copyright 2006, Google Inc. +** +** 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 "SkEvent.h" + +void SkEvent::initialize(const char* type, size_t typeLen) { + fType = NULL; + setType(type, typeLen); + f32 = 0; +#ifdef SK_DEBUG + fTargetID = 0; + fTime = 0; + fNextEvent = NULL; +#endif + SkDEBUGCODE(fDebugTrace = false;) +} + +SkEvent::SkEvent() +{ + initialize("", 0); +} + +SkEvent::SkEvent(const SkEvent& src) +{ + *this = src; + if (((size_t) fType & 1) == 0) + setType(src.fType); +} + +SkEvent::SkEvent(const SkString& type) +{ + initialize(type.c_str(), type.size()); +} + +SkEvent::SkEvent(const char type[]) +{ + SkASSERT(type); + initialize(type, strlen(type)); +} + +SkEvent::~SkEvent() +{ + if (((size_t) fType & 1) == 0) + sk_free((void*) fType); +} + +static size_t makeCharArray(char* buffer, size_t compact) +{ + size_t bits = (size_t) compact >> 1; + memcpy(buffer, &bits, sizeof(compact)); + buffer[sizeof(compact)] = 0; + return strlen(buffer); +} + +#if 0 +const char* SkEvent::getType() const +{ + if ((size_t) fType & 1) { // not a pointer + char chars[sizeof(size_t) + 1]; + size_t len = makeCharArray(chars, (size_t) fType); + fType = (char*) sk_malloc_throw(len); + SkASSERT(((size_t) fType & 1) == 0); + memcpy(fType, chars, len); + } + return fType; +} +#endif + +void SkEvent::getType(SkString* str) const +{ + if (str) + { + if ((size_t) fType & 1) // not a pointer + { + char chars[sizeof(size_t) + 1]; + size_t len = makeCharArray(chars, (size_t) fType); + str->set(chars, len); + } + else + str->set(fType); + } +} + +bool SkEvent::isType(const SkString& str) const +{ + return this->isType(str.c_str(), str.size()); +} + +bool SkEvent::isType(const char type[], size_t typeLen) const +{ + if (typeLen == 0) + typeLen = strlen(type); + if ((size_t) fType & 1) { // not a pointer + char chars[sizeof(size_t) + 1]; + size_t len = makeCharArray(chars, (size_t) fType); + return len == typeLen && strncmp(chars, type, typeLen) == 0; + } + return strncmp(fType, type, typeLen) == 0 && fType[typeLen] == 0; +} + +void SkEvent::setType(const char type[], size_t typeLen) +{ + if (typeLen == 0) + typeLen = strlen(type); + if (typeLen <= sizeof(fType)) { + size_t slot = 0; + memcpy(&slot, type, typeLen); + if (slot << 1 >> 1 != slot) + goto useCharStar; + slot <<= 1; + slot |= 1; + fType = (char*) slot; + } else { +useCharStar: + fType = (char*) sk_malloc_throw(typeLen + 1); + SkASSERT(((size_t) fType & 1) == 0); + memcpy(fType, type, typeLen); + fType[typeLen] = 0; + } +} + +void SkEvent::setType(const SkString& type) +{ + setType(type.c_str()); +} + +//////////////////////////////////////////////////////////////////////////// + +#include "SkParse.h" + +void SkEvent::inflate(const SkDOM& dom, const SkDOM::Node* node) +{ + const char* name = dom.findAttr(node, "type"); + if (name) + this->setType(name); + + const char* value; + if ((value = dom.findAttr(node, "fast32")) != NULL) + { + int32_t n; + if (SkParse::FindS32(value, &n)) + this->setFast32(n); + } + + for (node = dom.getFirstChild(node); node; node = dom.getNextSibling(node)) + { + if (strcmp(dom.getName(node), "data")) + { + SkDEBUGCODE(SkDebugf("SkEvent::inflate unrecognized subelement <%s>\n", dom.getName(node));) + continue; + } + + name = dom.findAttr(node, "name"); + if (name == NULL) + { + SkDEBUGCODE(SkDebugf("SkEvent::inflate missing required \"name\" attribute in <data> subelement\n");) + continue; + } + + if ((value = dom.findAttr(node, "s32")) != NULL) + { + int32_t n; + if (SkParse::FindS32(value, &n)) + this->setS32(name, n); + } + else if ((value = dom.findAttr(node, "scalar")) != NULL) + { + SkScalar x; + if (SkParse::FindScalar(value, &x)) + this->setScalar(name, x); + } + else if ((value = dom.findAttr(node, "string")) != NULL) + this->setString(name, value); +#ifdef SK_DEBUG + else + { + SkDebugf("SkEvent::inflate <data name=\"%s\"> subelement missing required type attribute [S32 | scalar | string]\n", name); + } +#endif + } +} + +#ifdef SK_DEBUG + + #ifndef SkScalarToFloat + #define SkScalarToFloat(x) ((x) / 65536.f) + #endif + + void SkEvent::dump(const char title[]) + { + if (title) + SkDebugf("%s ", title); + + SkString etype; + this->getType(&etype); + SkDebugf("event<%s> fast32=%d", etype.c_str(), this->getFast32()); + + const SkMetaData& md = this->getMetaData(); + SkMetaData::Iter iter(md); + SkMetaData::Type mtype; + int count; + const char* name; + + while ((name = iter.next(&mtype, &count)) != NULL) + { + SkASSERT(count > 0); + + SkDebugf(" <%s>=", name); + switch (mtype) { + case SkMetaData::kS32_Type: // vector version??? + { + int32_t value; + md.findS32(name, &value); + SkDebugf("%d ", value); + } + break; + case SkMetaData::kScalar_Type: + { + const SkScalar* values = md.findScalars(name, &count, NULL); + SkDebugf("%f", SkScalarToFloat(values[0])); + for (int i = 1; i < count; i++) + SkDebugf(", %f", SkScalarToFloat(values[i])); + SkDebugf(" "); + } + break; + case SkMetaData::kString_Type: + { + const char* value = md.findString(name); + SkASSERT(value); + SkDebugf("<%s> ", value); + } + break; + case SkMetaData::kPtr_Type: // vector version??? + { + void* value; + md.findPtr(name, &value); + SkDebugf("%p ", value); + } + break; + case SkMetaData::kBool_Type: // vector version??? + { + bool value; + md.findBool(name, &value); + SkDebugf("%s ", value ? "true" : "false"); + } + break; + default: + SkASSERT(!"unknown metadata type returned from iterator"); + break; + } + } + SkDebugf("\n"); + } +#endif + +/////////////////////////////////////////////////////////////////////////////////////// + +#ifdef SK_DEBUG +// #define SK_TRACE_EVENTSx +#endif + +#ifdef SK_TRACE_EVENTS + static void event_log(const char s[]) + { + SkDEBUGF(("%s\n", s)); + } + + #define EVENT_LOG(s) event_log(s) + #define EVENT_LOGN(s, n) do { SkString str(s); str.append(" "); str.appendS32(n); event_log(str.c_str()); } while (0) +#else + #define EVENT_LOG(s) + #define EVENT_LOGN(s, n) +#endif + +#include "SkGlobals.h" +#include "SkThread.h" +#include "SkTime.h" + +#define SK_Event_GlobalsTag SkSetFourByteTag('e', 'v', 'n', 't') + +class SkEvent_Globals : public SkGlobals::Rec { +public: + SkMutex fEventMutex; + SkEvent* fEventQHead, *fEventQTail; + SkEvent* fDelayQHead; + SkDEBUGCODE(int fEventCounter;) +}; + +static SkGlobals::Rec* create_globals() +{ + SkEvent_Globals* rec = new SkEvent_Globals; + rec->fEventQHead = NULL; + rec->fEventQTail = NULL; + rec->fDelayQHead = NULL; + SkDEBUGCODE(rec->fEventCounter = 0;) + return rec; +} + +bool SkEvent::Post(SkEvent* evt, SkEventSinkID sinkID, SkMSec delay) +{ + if (delay) + return SkEvent::PostTime(evt, sinkID, SkTime::GetMSecs() + delay); + + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + + evt->fTargetID = sinkID; + +#ifdef SK_TRACE_EVENTS + { + SkString str("SkEvent::Post("); + str.append(evt->getType()); + str.append(", 0x"); + str.appendHex(sinkID); + str.append(", "); + str.appendS32(delay); + str.append(")"); + event_log(str.c_str()); + } +#endif + + globals.fEventMutex.acquire(); + bool wasEmpty = SkEvent::Enqueue(evt); + globals.fEventMutex.release(); + + // call outside of us holding the mutex + if (wasEmpty) + SkEvent::SignalNonEmptyQueue(); + return true; +} + +#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(SK_FIND_MEMORY_LEAKS) +SkMSec gMaxDrawTime; +#endif + +bool SkEvent::PostTime(SkEvent* evt, SkEventSinkID sinkID, SkMSec time) +{ +#if defined(SK_SIMULATE_FAILED_MALLOC) && defined(SK_FIND_MEMORY_LEAKS) + gMaxDrawTime = time; +#endif + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + + evt->fTargetID = sinkID; + +#ifdef SK_TRACE_EVENTS + { + SkString str("SkEvent::Post("); + str.append(evt->getType()); + str.append(", 0x"); + str.appendHex(sinkID); + str.append(", "); + str.appendS32(time); + str.append(")"); + event_log(str.c_str()); + } +#endif + + globals.fEventMutex.acquire(); + SkMSec queueDelay = SkEvent::EnqueueTime(evt, time); + globals.fEventMutex.release(); + + // call outside of us holding the mutex + if ((int32_t)queueDelay != ~0) + SkEvent::SignalQueueTimer(queueDelay); + return true; +} + +bool SkEvent::Enqueue(SkEvent* evt) +{ + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + // gEventMutex acquired by caller + + SkASSERT(evt); + + bool wasEmpty = globals.fEventQHead == NULL; + + if (globals.fEventQTail) + globals.fEventQTail->fNextEvent = evt; + globals.fEventQTail = evt; + if (globals.fEventQHead == NULL) + globals.fEventQHead = evt; + evt->fNextEvent = NULL; + + SkDEBUGCODE(++globals.fEventCounter); +// SkDebugf("Enqueue: count=%d\n", gEventCounter); + + return wasEmpty; +} + +SkEvent* SkEvent::Dequeue(SkEventSinkID* sinkID) +{ + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + globals.fEventMutex.acquire(); + + SkEvent* evt = globals.fEventQHead; + if (evt) + { + SkDEBUGCODE(--globals.fEventCounter); + + if (sinkID) + *sinkID = evt->fTargetID; + + globals.fEventQHead = evt->fNextEvent; + if (globals.fEventQHead == NULL) + globals.fEventQTail = NULL; + } + globals.fEventMutex.release(); + +// SkDebugf("Dequeue: count=%d\n", gEventCounter); + + return evt; +} + +bool SkEvent::QHasEvents() +{ + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + + // this is not thread accurate, need a semaphore for that + return globals.fEventQHead != NULL; +} + +#ifdef SK_TRACE_EVENTS + static int gDelayDepth; +#endif + +SkMSec SkEvent::EnqueueTime(SkEvent* evt, SkMSec time) +{ +#ifdef SK_TRACE_EVENTS + SkDebugf("enqueue-delay %s %d (%d)", evt->getType(), time, gDelayDepth); + const char* idStr = evt->findString("id"); + if (idStr) + SkDebugf(" (%s)", idStr); + SkDebugf("\n"); + ++gDelayDepth; +#endif + + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + // gEventMutex acquired by caller + + SkEvent* curr = globals.fDelayQHead; + SkEvent* prev = NULL; + + while (curr) + { + if (SkMSec_LT(time, curr->fTime)) + break; + prev = curr; + curr = curr->fNextEvent; + } + + evt->fTime = time; + evt->fNextEvent = curr; + if (prev == NULL) + globals.fDelayQHead = evt; + else + prev->fNextEvent = evt; + + SkMSec delay = globals.fDelayQHead->fTime - SkTime::GetMSecs(); + if ((int32_t)delay <= 0) + delay = 1; + return delay; +} + +////////////////////////////////////////////////////////////////////////////// + +#include "SkEventSink.h" + +bool SkEvent::ProcessEvent() +{ + SkEventSinkID sinkID; + SkEvent* evt = SkEvent::Dequeue(&sinkID); + SkAutoTDelete<SkEvent> autoDelete(evt); + bool again = false; + + EVENT_LOGN("ProcessEvent", (int32_t)evt); + + if (evt) + { + (void)SkEventSink::DoEvent(*evt, sinkID); + again = SkEvent::QHasEvents(); + } + return again; +} + +void SkEvent::ServiceQueueTimer() +{ + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + + globals.fEventMutex.acquire(); + + bool wasEmpty = false; + SkMSec now = SkTime::GetMSecs(); + SkEvent* evt = globals.fDelayQHead; + + while (evt) + { + if (SkMSec_LT(now, evt->fTime)) + break; + +#ifdef SK_TRACE_EVENTS + --gDelayDepth; + SkDebugf("dequeue-delay %s (%d)", evt->getType(), gDelayDepth); + const char* idStr = evt->findString("id"); + if (idStr) + SkDebugf(" (%s)", idStr); + SkDebugf("\n"); +#endif + + SkEvent* next = evt->fNextEvent; + if (SkEvent::Enqueue(evt)) + wasEmpty = true; + evt = next; + } + globals.fDelayQHead = evt; + + SkMSec time = evt ? evt->fTime - now : 0; + + globals.fEventMutex.release(); + + if (wasEmpty) + SkEvent::SignalNonEmptyQueue(); + + SkEvent::SignalQueueTimer(time); +} + +//////////////////////////////////////////////////////////////// + +void SkEvent::Init() +{ +} + +void SkEvent::Term() +{ + SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals); + + SkEvent* evt = globals.fEventQHead; + while (evt) + { + SkEvent* next = evt->fNextEvent; + delete evt; + evt = next; + } + + evt = globals.fDelayQHead; + while (evt) + { + SkEvent* next = evt->fNextEvent; + delete evt; + evt = next; + } +} + |