1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/2d/Logging.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,239 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef MOZILLA_GFX_LOGGING_H_ 1.10 +#define MOZILLA_GFX_LOGGING_H_ 1.11 + 1.12 +#include <string> 1.13 +#include <sstream> 1.14 +#include <stdio.h> 1.15 + 1.16 +#include "nsDebug.h" 1.17 +#include "Point.h" 1.18 +#include "BaseRect.h" 1.19 +#include "Matrix.h" 1.20 +#include "mozilla/TypedEnum.h" 1.21 + 1.22 +#ifdef WIN32 1.23 +// This file gets included from nsGlobalWindow.cpp, which doesn't like 1.24 +// having windows.h included in it. Since OutputDebugStringA is the only 1.25 +// thing we need from windows.h, we just declare it here directly. 1.26 +// Note: the function's documented signature is 1.27 +// WINBASEAPI void WINAPI OutputDebugStringA(LPCSTR lpOutputString) 1.28 +// but if we don't include windows.h, the macros WINBASEAPI, WINAPI, and 1.29 +// LPCSTR are not defined, so we need to replace them with their expansions. 1.30 +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString); 1.31 +#endif 1.32 + 1.33 +#if defined(DEBUG) || defined(PR_LOGGING) 1.34 +#include <prlog.h> 1.35 + 1.36 +extern GFX2D_API PRLogModuleInfo *GetGFX2DLog(); 1.37 +#endif 1.38 + 1.39 +namespace mozilla { 1.40 +namespace gfx { 1.41 + 1.42 +const int LOG_DEBUG = 1; 1.43 +const int LOG_WARNING = 2; 1.44 + 1.45 +#if defined(DEBUG) || defined(PR_LOGGING) 1.46 + 1.47 +inline PRLogModuleLevel PRLogLevelForLevel(int aLevel) { 1.48 + switch (aLevel) { 1.49 + case LOG_DEBUG: 1.50 + return PR_LOG_DEBUG; 1.51 + case LOG_WARNING: 1.52 + return PR_LOG_WARNING; 1.53 + } 1.54 + return PR_LOG_DEBUG; 1.55 +} 1.56 + 1.57 +#endif 1.58 + 1.59 +extern GFX2D_API int sGfxLogLevel; 1.60 + 1.61 +static inline void OutputMessage(const std::string &aString, int aLevel) { 1.62 +#if defined(WIN32) && !defined(PR_LOGGING) 1.63 + if (aLevel >= sGfxLogLevel) { 1.64 + ::OutputDebugStringA(aString.c_str()); 1.65 + } 1.66 +#elif defined(PR_LOGGING) && !(defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID)) 1.67 + if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) { 1.68 + PR_LogPrint(aString.c_str()); 1.69 + } 1.70 +#else 1.71 + if (aLevel >= sGfxLogLevel) { 1.72 + printf_stderr("%s", aString.c_str()); 1.73 + } 1.74 +#endif 1.75 +} 1.76 + 1.77 +class NoLog 1.78 +{ 1.79 +public: 1.80 + NoLog() {} 1.81 + ~NoLog() {} 1.82 + 1.83 + template<typename T> 1.84 + NoLog &operator <<(const T &aLogText) { return *this; } 1.85 +}; 1.86 + 1.87 +MOZ_BEGIN_ENUM_CLASS(LogOptions, int) 1.88 + NoNewline = 0x01 1.89 +MOZ_END_ENUM_CLASS(LogOptions) 1.90 + 1.91 +template<int L> 1.92 +class Log 1.93 +{ 1.94 +public: 1.95 + Log(LogOptions aOptions = LogOptions(0)) : mOptions(aOptions) {} 1.96 + ~Log() { 1.97 + Flush(); 1.98 + } 1.99 + 1.100 + void Flush() { 1.101 + if (!(int(mOptions) & int(LogOptions::NoNewline))) { 1.102 + mMessage << '\n'; 1.103 + } 1.104 + std::string str = mMessage.str(); 1.105 + if (!str.empty()) { 1.106 + WriteLog(str); 1.107 + } 1.108 + mMessage.str(""); 1.109 + mMessage.clear(); 1.110 + } 1.111 + 1.112 + Log &operator <<(char aChar) { mMessage << aChar; return *this; } 1.113 + Log &operator <<(const std::string &aLogText) { mMessage << aLogText; return *this; } 1.114 + Log &operator <<(const char aStr[]) { mMessage << static_cast<const char*>(aStr); return *this; } 1.115 + Log &operator <<(bool aBool) { mMessage << (aBool ? "true" : "false"); return *this; } 1.116 + Log &operator <<(int aInt) { mMessage << aInt; return *this; } 1.117 + Log &operator <<(unsigned int aInt) { mMessage << aInt; return *this; } 1.118 + Log &operator <<(long aLong) { mMessage << aLong; return *this; } 1.119 + Log &operator <<(unsigned long aLong) { mMessage << aLong; return *this; } 1.120 + Log &operator <<(long long aLong) { mMessage << aLong; return *this; } 1.121 + Log &operator <<(unsigned long long aLong) { mMessage << aLong; return *this; } 1.122 + Log &operator <<(Float aFloat) { mMessage << aFloat; return *this; } 1.123 + Log &operator <<(double aDouble) { mMessage << aDouble; return *this; } 1.124 + template <typename T, typename Sub> 1.125 + Log &operator <<(const BasePoint<T, Sub>& aPoint) 1.126 + { mMessage << "Point(" << aPoint.x << "," << aPoint.y << ")"; return *this; } 1.127 + template <typename T, typename Sub> 1.128 + Log &operator <<(const BaseSize<T, Sub>& aSize) 1.129 + { mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; return *this; } 1.130 + template <typename T, typename Sub, typename Point, typename SizeT, typename Margin> 1.131 + Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect) 1.132 + { mMessage << "Rect(" << aRect.x << "," << aRect.y << "," << aRect.width << "," << aRect.height << ")"; return *this; } 1.133 + Log &operator<<(const Matrix& aMatrix) 1.134 + { mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; return *this; } 1.135 + 1.136 + 1.137 +private: 1.138 + 1.139 + void WriteLog(const std::string &aString) { 1.140 + OutputMessage(aString, L); 1.141 + } 1.142 + 1.143 + std::stringstream mMessage; 1.144 + LogOptions mOptions; 1.145 +}; 1.146 + 1.147 +typedef Log<LOG_DEBUG> DebugLog; 1.148 +typedef Log<LOG_WARNING> WarningLog; 1.149 + 1.150 +#ifdef GFX_LOG_DEBUG 1.151 +#define gfxDebug DebugLog 1.152 +#else 1.153 +#define gfxDebug if (1) ; else NoLog 1.154 +#endif 1.155 +#ifdef GFX_LOG_WARNING 1.156 +#define gfxWarning WarningLog 1.157 +#else 1.158 +#define gfxWarning if (1) ; else NoLog 1.159 +#endif 1.160 + 1.161 +const int INDENT_PER_LEVEL = 2; 1.162 + 1.163 +class TreeLog 1.164 +{ 1.165 +public: 1.166 + TreeLog(const std::string& aPrefix = "") 1.167 + : mLog(LogOptions::NoNewline), 1.168 + mPrefix(aPrefix), 1.169 + mDepth(0), 1.170 + mStartOfLine(true), 1.171 + mConditionedOnPref(false), 1.172 + mPref(nullptr) {} 1.173 + 1.174 + template <typename T> 1.175 + TreeLog& operator<<(const T& aObject) { 1.176 + if (mConditionedOnPref && !*mPref) { 1.177 + return *this; 1.178 + } 1.179 + if (mStartOfLine) { 1.180 + mLog << '[' << mPrefix << "] " << std::string(mDepth * INDENT_PER_LEVEL, ' '); 1.181 + mStartOfLine = false; 1.182 + } 1.183 + mLog << aObject; 1.184 + if (EndsInNewline(aObject)) { 1.185 + // Don't indent right here as the user may change the indent 1.186 + // between now and the first output to the next line. 1.187 + mLog.Flush(); 1.188 + mStartOfLine = true; 1.189 + } 1.190 + return *this; 1.191 + } 1.192 + 1.193 + void IncreaseIndent() { ++mDepth; } 1.194 + void DecreaseIndent() { --mDepth; } 1.195 + 1.196 + void ConditionOnPref(bool* aPref) { 1.197 + mConditionedOnPref = true; 1.198 + mPref = aPref; 1.199 + } 1.200 +private: 1.201 + Log<LOG_DEBUG> mLog; 1.202 + std::string mPrefix; 1.203 + uint32_t mDepth; 1.204 + bool mStartOfLine; 1.205 + bool mConditionedOnPref; 1.206 + bool* mPref; 1.207 + 1.208 + template <typename T> 1.209 + static bool EndsInNewline(const T& aObject) { 1.210 + return false; 1.211 + } 1.212 + 1.213 + static bool EndsInNewline(const std::string& aString) { 1.214 + return !aString.empty() && aString[aString.length() - 1] == '\n'; 1.215 + } 1.216 + 1.217 + static bool EndsInNewline(char aChar) { 1.218 + return aChar == '\n'; 1.219 + } 1.220 + 1.221 + static bool EndsInNewline(const char* aString) { 1.222 + return EndsInNewline(std::string(aString)); 1.223 + } 1.224 +}; 1.225 + 1.226 +class TreeAutoIndent 1.227 +{ 1.228 +public: 1.229 + TreeAutoIndent(TreeLog& aTreeLog) : mTreeLog(aTreeLog) { 1.230 + mTreeLog.IncreaseIndent(); 1.231 + } 1.232 + ~TreeAutoIndent() { 1.233 + mTreeLog.DecreaseIndent(); 1.234 + } 1.235 +private: 1.236 + TreeLog& mTreeLog; 1.237 +}; 1.238 + 1.239 +} 1.240 +} 1.241 + 1.242 +#endif /* MOZILLA_GFX_LOGGING_H_ */