Bumping manifests a=b2g-bump
[gecko.git] / gfx / 2d / Logging.h
blob6d5701e9d31e2f82c5043ff945ac1f96c0171ed2
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef MOZILLA_GFX_LOGGING_H_
7 #define MOZILLA_GFX_LOGGING_H_
9 #include <string>
10 #include <sstream>
11 #include <stdio.h>
13 #include "nsDebug.h"
14 #include "Point.h"
15 #include "BaseRect.h"
16 #include "Matrix.h"
17 #include "mozilla/TypedEnum.h"
19 #ifdef WIN32
20 // This file gets included from nsGlobalWindow.cpp, which doesn't like
21 // having windows.h included in it. Since OutputDebugStringA is the only
22 // thing we need from windows.h, we just declare it here directly.
23 // Note: the function's documented signature is
24 // WINBASEAPI void WINAPI OutputDebugStringA(LPCSTR lpOutputString)
25 // but if we don't include windows.h, the macros WINBASEAPI, WINAPI, and
26 // LPCSTR are not defined, so we need to replace them with their expansions.
27 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA(const char* lpOutputString);
28 #endif
30 #if defined(DEBUG) || defined(PR_LOGGING)
31 #include <prlog.h>
33 extern GFX2D_API PRLogModuleInfo *GetGFX2DLog();
34 #endif
36 namespace mozilla {
37 namespace gfx {
39 const int LOG_DEBUG = 1;
40 const int LOG_WARNING = 2;
42 #if defined(DEBUG) || defined(PR_LOGGING)
44 inline PRLogModuleLevel PRLogLevelForLevel(int aLevel) {
45 switch (aLevel) {
46 case LOG_DEBUG:
47 return PR_LOG_DEBUG;
48 case LOG_WARNING:
49 return PR_LOG_WARNING;
51 return PR_LOG_DEBUG;
54 #endif
56 extern GFX2D_API int sGfxLogLevel;
58 static inline void OutputMessage(const std::string &aString, int aLevel) {
59 #if defined(WIN32) && !defined(PR_LOGGING)
60 if (aLevel >= sGfxLogLevel) {
61 ::OutputDebugStringA(aString.c_str());
63 #elif defined(PR_LOGGING) && !(defined(MOZ_WIDGET_GONK) || defined(MOZ_WIDGET_ANDROID))
64 if (PR_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) {
65 PR_LogPrint(aString.c_str());
67 #else
68 if (aLevel >= sGfxLogLevel) {
69 printf_stderr("%s", aString.c_str());
71 #endif
74 class NoLog
76 public:
77 NoLog() {}
78 ~NoLog() {}
80 template<typename T>
81 NoLog &operator <<(const T &aLogText) { return *this; }
84 MOZ_BEGIN_ENUM_CLASS(LogOptions, int)
85 NoNewline = 0x01
86 MOZ_END_ENUM_CLASS(LogOptions)
88 template<int L>
89 class Log
91 public:
92 explicit Log(LogOptions aOptions = LogOptions(0)) : mOptions(aOptions) {}
93 ~Log() {
94 Flush();
97 void Flush() {
98 if (!(int(mOptions) & int(LogOptions::NoNewline))) {
99 mMessage << '\n';
101 std::string str = mMessage.str();
102 if (!str.empty()) {
103 WriteLog(str);
105 mMessage.str("");
106 mMessage.clear();
109 Log &operator <<(char aChar) { mMessage << aChar; return *this; }
110 Log &operator <<(const std::string &aLogText) { mMessage << aLogText; return *this; }
111 Log &operator <<(const char aStr[]) { mMessage << static_cast<const char*>(aStr); return *this; }
112 Log &operator <<(bool aBool) { mMessage << (aBool ? "true" : "false"); return *this; }
113 Log &operator <<(int aInt) { mMessage << aInt; return *this; }
114 Log &operator <<(unsigned int aInt) { mMessage << aInt; return *this; }
115 Log &operator <<(long aLong) { mMessage << aLong; return *this; }
116 Log &operator <<(unsigned long aLong) { mMessage << aLong; return *this; }
117 Log &operator <<(long long aLong) { mMessage << aLong; return *this; }
118 Log &operator <<(unsigned long long aLong) { mMessage << aLong; return *this; }
119 Log &operator <<(Float aFloat) { mMessage << aFloat; return *this; }
120 Log &operator <<(double aDouble) { mMessage << aDouble; return *this; }
121 template <typename T, typename Sub>
122 Log &operator <<(const BasePoint<T, Sub>& aPoint)
123 { mMessage << "Point" << aPoint; return *this; }
124 template <typename T, typename Sub>
125 Log &operator <<(const BaseSize<T, Sub>& aSize)
126 { mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; return *this; }
127 template <typename T, typename Sub, typename Point, typename SizeT, typename Margin>
128 Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect)
129 { mMessage << "Rect" << aRect; return *this; }
130 Log &operator<<(const Matrix& aMatrix)
131 { mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; return *this; }
134 private:
136 void WriteLog(const std::string &aString) {
137 OutputMessage(aString, L);
140 std::stringstream mMessage;
141 LogOptions mOptions;
144 typedef Log<LOG_DEBUG> DebugLog;
145 typedef Log<LOG_WARNING> WarningLog;
147 #ifdef GFX_LOG_DEBUG
148 #define gfxDebug DebugLog
149 #else
150 #define gfxDebug if (1) ; else NoLog
151 #endif
152 #ifdef GFX_LOG_WARNING
153 #define gfxWarning WarningLog
154 #else
155 #define gfxWarning if (1) ; else NoLog
156 #endif
158 // See nsDebug.h and the NS_WARN_IF macro
160 #ifdef __cplusplus
161 #ifdef DEBUG
162 inline bool MOZ2D_warn_if_impl(bool aCondition, const char* aExpr,
163 const char* aFile, int32_t aLine)
165 if (MOZ_UNLIKELY(aCondition)) {
166 gfxWarning() << aExpr << " at " << aFile << ":" << aLine;
168 return aCondition;
170 #define MOZ2D_WARN_IF(condition) \
171 MOZ2D_warn_if_impl(condition, #condition, __FILE__, __LINE__)
172 #else
173 #define MOZ2D_WARN_IF(condition) (bool)(condition)
174 #endif
175 #endif
177 const int INDENT_PER_LEVEL = 2;
179 class TreeLog
181 public:
182 explicit TreeLog(const std::string& aPrefix = "")
183 : mLog(LogOptions::NoNewline),
184 mPrefix(aPrefix),
185 mDepth(0),
186 mStartOfLine(true),
187 mConditionedOnPref(false),
188 mPrefFunction(nullptr) {}
190 template <typename T>
191 TreeLog& operator<<(const T& aObject) {
192 if (mConditionedOnPref && !mPrefFunction()) {
193 return *this;
195 if (mStartOfLine) {
196 mLog << '[' << mPrefix << "] " << std::string(mDepth * INDENT_PER_LEVEL, ' ');
197 mStartOfLine = false;
199 mLog << aObject;
200 if (EndsInNewline(aObject)) {
201 // Don't indent right here as the user may change the indent
202 // between now and the first output to the next line.
203 mLog.Flush();
204 mStartOfLine = true;
206 return *this;
209 void IncreaseIndent() { ++mDepth; }
210 void DecreaseIndent() { --mDepth; }
212 void ConditionOnPrefFunction(bool(*aPrefFunction)()) {
213 mConditionedOnPref = true;
214 mPrefFunction = aPrefFunction;
216 private:
217 Log<LOG_DEBUG> mLog;
218 std::string mPrefix;
219 uint32_t mDepth;
220 bool mStartOfLine;
221 bool mConditionedOnPref;
222 bool (*mPrefFunction)();
224 template <typename T>
225 static bool EndsInNewline(const T& aObject) {
226 return false;
229 static bool EndsInNewline(const std::string& aString) {
230 return !aString.empty() && aString[aString.length() - 1] == '\n';
233 static bool EndsInNewline(char aChar) {
234 return aChar == '\n';
237 static bool EndsInNewline(const char* aString) {
238 return EndsInNewline(std::string(aString));
242 class TreeAutoIndent
244 public:
245 explicit TreeAutoIndent(TreeLog& aTreeLog) : mTreeLog(aTreeLog) {
246 mTreeLog.IncreaseIndent();
248 ~TreeAutoIndent() {
249 mTreeLog.DecreaseIndent();
251 private:
252 TreeLog& mTreeLog;
258 #endif /* MOZILLA_GFX_LOGGING_H_ */