最近考慮開發一款兵棋軟件,名字都想好了,叫犀牛兵棋,打算支持四邊形地圖和六邊形地圖。
前者比較好說,后者在根據屏幕坐標計算格子坐標的時候,稍微有點麻煩。
先說下我們的坐標系是x軸向右,y軸向上,原點在左下角。
格子地圖坐標如下

根據格子坐標計算出對應世界坐標系的函數如下
QPointF GridCell6Manager::getWorldPosByCellCoordinate(int x,int y)
{
if (x % 2 == 0)
return QPointF(1.5f*res*(x+1),
(0.5*R3+R3*y)*res);
return QPointF(1.5f*res*(x + 1),
(R3 + y * R3)*res);
}
QPoint GridCell6Manager::getCellCoordinateByWorldPos(int x,int y)
{
QPoint point(-1,-1);
float xpos = x-res*0.5f;
float ypos = y/(R3*res) - 0.5f;
int yset[2] = {std::floorf(ypos),std::ceilf(ypos)};
xpos /= (1.5*World::getInstance().getWorldResolution());
int xset[2] = { std::floorf(xpos),std::ceilf(xpos)};
auto p00 = getWorldPosByCellCoordinate(xset[0],yset[0]);
auto p01 = getWorldPosByCellCoordinate(xset[0],yset[1]);
auto p10 = getWorldPosByCellCoordinate(xset[1],yset[0]);
auto p11 = getWorldPosByCellCoordinate(xset[1],yset[1]);
float d00 = distance2<float>(x,y,p00.x(),p00.y());
float d01 = distance2<float>(x,y,p01.x(),p01.y());
float d10 = distance2<float>(x,y,p10.x(),p10.y());
float d11 = distance2<float>(x,y,p11.x(),p11.y());
int i,j;
if(d00 < d01 && d00 < d10 && d00 < d11)
{
i = xset[0];
j = yset[0];
}
else if(d00 > d01 && d01 < d10 && d01 < d11)
{
i = xset[0];
j = yset[1];
}
else if(d10 < d00 && d10 < d01 && d10 < d11)
{
i = xset[1];
j = yset[0];
}
else
{
i = xset[1];
j = yset[1];
}
return QPoint(i,j);
}
其中res為格子邊長,R3為sqrt(3)常量
在這個基礎上就可以計算從世界坐標到格子坐標的轉換了
#include <Windows.h>
#include <wininet.h>
#include <stdio.h>
#include <string>
#include <io.h>
using namespace std;
#pragma comment(lib, "wininet.lib")
const DWORD DWORD_MAX_CCH_OF_TEST_URL = 256;
const DWORD DWORD_MAX_CCH_OF_HOST_NAME = 128;
const DWORD DWORD_MAX_CCH_OF_URL_PATH = 256;
int breakpointDownload(const std::wstring& url, const std::wstring& folder, void(*cb)(double),std::wstring& name)
{
int index = url.find_last_of(L'/');
std::wstring filename = url.substr(index + 1);
index = filename.find_first_of(L'?');
if (index != std::wstring::npos)
filename = filename.substr(0,index);
if (!folder.empty())
filename = folder + L"\\" + filename;
std::wstring tempfile = filename + L".dl";
_wremove(filename.c_str());
HINTERNET hInetOpen = NULL;
HINTERNET hInetConnect = NULL;
HINTERNET hInetRequest = NULL;
HANDLE lhFile = NULL;
URL_COMPONENTS ldCrackedURL;
ZeroMemory(&ldCrackedURL, sizeof(URL_COMPONENTS));
ldCrackedURL.dwStructSize = sizeof(URL_COMPONENTS);
TCHAR szHostName[DWORD_MAX_CCH_OF_HOST_NAME] = { 0 };
ldCrackedURL.lpszHostName = szHostName;
ldCrackedURL.dwHostNameLength = DWORD_MAX_CCH_OF_HOST_NAME;
wchar_t szUrlPath[DWORD_MAX_CCH_OF_URL_PATH] = { 0 };
ldCrackedURL.lpszUrlPath = szUrlPath;
ldCrackedURL.dwUrlPathLength = DWORD_MAX_CCH_OF_URL_PATH;
if (FALSE == InternetCrackUrl(url.c_str(),url.size(), 0, &ldCrackedURL))
{
return 0;
}
hInetOpen = InternetOpen(L"MSIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (NULL == hInetOpen)
{
return 0;
}
hInetConnect = InternetConnect(hInetOpen, ldCrackedURL.lpszHostName, ldCrackedURL.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (NULL == hInetConnect)
{
return 0;
}
lhFile = CreateFile(tempfile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (lhFile == INVALID_HANDLE_VALUE)
{
return 0;
}
LARGE_INTEGER ldFileSize;
if (FALSE == GetFileSizeEx(lhFile, &ldFileSize))
{
return 0;
}
LONGLONG lllStartPos = 0;
if(0 == ldFileSize.QuadPart)
{
}
else
{
if (INVALID_SET_FILE_POINTER == SetFilePointer(lhFile, 0, NULL, FILE_END))
{
return 0;
}
lllStartPos = ldFileSize.QuadPart;
}
wchar_t lscRangeStartPosition[30] = { 0 };
if (0 != _i64tow_s((__int64)(lllStartPos), lscRangeStartPosition, sizeof(lscRangeStartPosition), 10))
{
return 0;
}
wstring loAdditionalHeader = L"Range: bytes=";
loAdditionalHeader += lscRangeStartPosition;
loAdditionalHeader += L"-\r\n";
const wchar_t* lplpszAcceptTypes[] = { L"*/*", NULL };
hInetRequest = HttpOpenRequest(hInetConnect,L"GET", ldCrackedURL.lpszUrlPath,L"HTTP/1.1", NULL,lplpszAcceptTypes, 0, 0);
if (NULL == hInetConnect)
{
return 0;
}
if (FALSE == HttpSendRequest(hInetRequest, loAdditionalHeader.c_str(), loAdditionalHeader.size(), NULL, 0))
{
return 0;
}
DWORD ldwStatusCode;
DWORD ldwCbOfStatusCode = sizeof(ldwStatusCode);
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &ldwStatusCode, &ldwCbOfStatusCode, 0))
{
return 0;
}
if (416 == ldwStatusCode)
{
_wrename(tempfile.c_str(), filename.c_str());
name = filename;
return 1;
}
else if (200 != ldwStatusCode && 206 != ldwStatusCode)
{
return 0;
}
DWORD dwFile = 10000;
DWORD dwSize = sizeof(DWORD);
if (FALSE == HttpQueryInfo(hInetRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFile, &dwSize, 0))
{
}
else
dwFile += lllStartPos;
BYTE lpbBufferToReceiveData[2048];
DWORD ldwCbBuffer = 2048;
DWORD ldwCrtCbReaded;
DWORD ldwCbWritten = 0;
bool lbIsOk = false;
LONGLONG lllCbAllRead = lllStartPos;
do
{
if (FALSE == InternetReadFile(hInetRequest, lpbBufferToReceiveData, ldwCbBuffer, &ldwCrtCbReaded))
{
break;
}
if (ldwCrtCbReaded == 0)
{
break;
}
if (FALSE == WriteFile(lhFile, lpbBufferToReceiveData, ldwCrtCbReaded, &ldwCbWritten, NULL) || ldwCbWritten != ldwCrtCbReaded)
{
break;
}
ZeroMemory(lpbBufferToReceiveData, ldwCrtCbReaded);
lllCbAllRead += ldwCrtCbReaded;
double p = lllCbAllRead * 100.0 / dwFile;
if (p > 100)
p = 100;
if (cb)
cb(p);
} while (true);
if (NULL != lhFile)
{
CloseHandle(lhFile);
}
if (NULL != hInetRequest)
{
InternetCloseHandle(hInetRequest);
}
if (NULL != hInetConnect)
{
InternetCloseHandle(hInetConnect);
}
if (NULL != hInetOpen)
{
InternetCloseHandle(hInetOpen);
}
_wrename(tempfile.c_str(), filename.c_str());
name = filename;
return 1;
}
使用Qt開發的,具體涉及QNetwork/Qjson/QChart等各個Qt模塊
軟件支持日線,分時,周線,月線等不同周期的混合量化分析;支持選股和回測二個模式;支持K線識別;支持常見的10多種技術指標;
同時還支持基于LEVEL2的資金流分析和查看。
為了方便使用,我還自行開發了一套腳本解釋系統
一個macd金叉死叉的量化腳本如下:
#設置K線文件目錄
config.source.k.dir=data
#設置分筆數據文件目錄
config.source.ticket.dir=ticket
#設置level2文件路徑
config.source.lv2.dir=lv2
#設置K線數據格式
config.source.k.format=default
#設置分時最大加載日期數
source.ticket.maxtickloaded=5
#設置小單最大額度
config.source.lv2.v1=5
#設置中單最大額度
config.source.lv2.v2=100
#設置大單最大額度,超過此數值則為超大單
config.source.lv2.v3=500
#定義單日股票買入排序,默認為成交量降序(可選volasc,increaseasc,increasedesc)
config.trade.buy.order=voldesc
#定義股票買入時機,默認為開盤(可選open/auto)
config.trade.buy.point=open
#定義股票賣出時機,默認為尾盤(可選第二天開盤價-早盤)
config.trade.sale.point=close
#是否使用立即止盈模式,達到設定盈利立刻賣出
config.trade.sale.rapid=yes
#設置單股最大持有日期
config.trade.max.hold.day=3
#設定單股買入后再次買入禁買日期間隔
config.trade.min.exclude=6
#設置止盈點
config.trade.max.profit=64.0
#設定止損點
config.trade.max.lost=-9.0
#設定交易成本(千分之.)
config.trade.tradecost=0.8
#設定單日最大可買股票數
config.trade.max.count=3
#設定股票買入最大允許漲幅
config.trade.max.allow.increase=3.2
#設定股票買入最大允許跌幅
config.trade.max.allow.decrease=-3.2
buy.macd.diff,0>macd.dea,0
buy.macd.diff,-1<macd.dea,-1
buy.macd.diff,0>value,0.0
buy.ohlc.increase,0>value,0.5
很容易理解吧

有興趣可以在www.snail007.com下載使用
Libcefwenjianjia文件夾比較簡單
分別是瀏覽器,基礎類,渲染類以及打印輸出(utility)相關
Chromium下的目錄結構很多,可分為幾類:編譯相關,實驗性工程相關,谷歌瀏覽器相關,專有庫相關,代碼相關
l Android_webview Android上的webview控件
l Apps Chrome程序相關
l Ash插件相關
l Base 提供公共的功能代碼
l Blimp 支持裁剪Chrome的谷歌實驗性項目
l Blink 沒用
l Breakpad開源崩潰報告項目
l Build 構建配置
l BuildTools 同上
l Cc 谷歌合成器(chromium compositor)實現部分 涉及幀/層的渲染布局以及圖形合成
l Cef Chrome的Cef封裝
l Chrome 谷歌瀏覽器程序核心代碼
l Chrome_elf 錯誤崩潰報告動態鏈接庫實現
l ChromeCast Chrome廣播相關
l ChromeOS
l Clound_Print 谷歌云打印相關
提供谷歌瀏覽器頁面預覽打印清單
l Components 瀏覽器基礎組建目錄和資源,比如關于界面資源和UI,Crash頁面顯示資源和界面等
l Content 多進程沙盒瀏覽器核心代碼
l Courgetter 谷歌提供的二進制文件對比核心算法,在谷歌瀏覽器中用于比較不同版本的二進制差異
l Cryto 加密庫
l Dbus 數據總線相關
l Device 提供輔助設備相關支持
,涉及藍牙,電池,NFC,USB等
l Docs
l Extensions 一個可復用的模塊,目前用于擴展Chrome瀏覽器
l Gin V8相關的便利類,提供字典,數字緩存等功能
l Google APIS
l Google update
l GPU 涉及blink,gl,ipc等
l Headless提供無頭瀏覽器模式
– 用于爬蟲,自動化測試等
l Infra 未知
l IOS IOS系統相關
l IPC 跨進程通信相關
l Jingle P2P傳輸庫
l Mandoline 一個基于Mojo腳本構建Chrome的實驗性庫
l Mash ?
l Media Chrome的多媒體模塊,支持音頻播放和錄音等功能
l Mojo 支持多類型的沙盒內容
l Native Client /Natice Client SDK支持在瀏覽器中執行多腳本語言而不限于js
l Net 網絡功能庫
l Pdf PDF格式相關
l PPAPI Chrome擴展插件框架
l Printing 打印相關
l Remoting 遠程控制和調試相關
l Rlz庫 用于統計軟件產品分發和市場使用統計相關
l SandBox 沙盒
l Sdch 一種壓縮格式
l Skia Skia圖像庫目前用于Chrome和Android
l Sql sqlite封裝庫
l Storage 數據儲存
l StyleGuide Chrome 代碼風格指南
l Sync Chrome賬號多數據同步
l Testing
l Third party 第三方庫集合
l Tools Chrome工具集
l UI Chrome UI庫
l URL 網頁鏈接解析相關
l V8 V8 js庫
l Win8 在windows上使chrome以metro模式展現
目前使用Cef框架的軟件很多,除了我們的程序,還有網易云音樂,StartUML,通信達等都基于Cef框架。閱讀Cef/Chrome底層代碼有助于了解他的設計架構和細節,可以幫助我們解決一些Cef框架層面的故障,同時可以學習他的編程思想和框架結構提高編程能力。本文主要介紹Cef3和Chromium,涉及Cef3/Chromium編譯,代碼目錄結構和具體功能實現細節,會根據需要不斷完善。需要指出的是Cef3/Chrome版本之間代碼框架,文件位置變動很多,如無特殊說明,本文以2623分支為基準。.
一 Cef3/Chromium的編譯和音視頻支持的修改
先說一點,國內從官網下載源碼網絡很不穩定,這里以別人下載好的cef2623版本來編譯
網盤地址: https://pan.baidu.com/s/1jHY4hls
編譯先決條件:win64系統,安裝python2.7 Virtual Studio2013 硬盤空間大于54G以上
下載完成后解壓 這里解壓到D盤下的2623目錄
打開CMD窗口 執行以下操作以設定環境變量
Set DEPOT_TOOLS_WIN_TOOLCHAIN=0
Set CEF_USE_GN=0
Set GYP_MSVS_VERSION=2013
Set GYP_GENERATORS=ninja,msvs-ninja
然后執行
python automate-git.py --download-dir=d:\cef3\source --branch=2623 --no-update --build-log-file --verbose-build --force-distrib --force-build
大致等待5個小時即可編譯完成
注意,指定—no-update 不更新代碼;如果不需要編譯debug版本,則需要指定
—no-debug-build
輸出目錄在src\cef\binary_distrib下
Cefclient.exe為demo程序,輸入www.html5test.com可查看支持音視頻的情況
當前編譯好的2623對音視頻的支持如下:
音視頻的支持有2處需要修改分別是
1是在source/chromium/src/cef/cef.gypi文件 在variables節點下增加
'proprietary_codecs': 1,
'ffmpeg_branding': 'Chrome',
2是修改二者
source\chromium\src\third_party\ffmpeg\chromium\config\Chrome\win\ia32\config.h
source\chromium\src\third_party\ffmpeg\chromium\config\Chrome\win\x64\config.h
在宏FFMPEG_CONFIGURATION 中增加
–enable-decoder=’rv10,rv20,rv30,rv40,cook,h263,h263i,mpeg4,msmpeg4v1,msmpeg4v2,msmpeg4v3,amrnb,amrwb,ac3,flv’
–enable-demuxer=’rm,mpegvideo,avi,avisynth,h263,aac,amr,ac3,flv,mpegts,mpegtsraw’
–enable-parser=’mpegvideo,rv30,rv40,h263,mpeg4video,ac3
可以根據需要修改要支持的音視頻情況
def psar(barsdata, iaf = 0.02, maxaf = 0.2):
length = len(barsdata)
dates = list(barsdata['Date'])
high = list(barsdata['High'])
low = list(barsdata['Low'])
close = list(barsdata['Close'])
psar = close[0:len(close)]
psarbull = [None] * length
psarbear = [None] * length
bull = True
af = iaf
ep = low[0]
hp = high[0]
lp = low[0]
for i in range(2,length):
if bull:
psar[i] = psar[i - 1] + af * (hp - psar[i - 1])
else:
psar[i] = psar[i - 1] + af * (lp - psar[i - 1])
reverse = False
if bull:
if low[i] < psar[i]:
bull = False
reverse = True
psar[i] = hp
lp = low[i]
af = iaf
else:
if high[i] > psar[i]:
bull = True
reverse = True
psar[i] = lp
hp = high[i]
af = iaf
if not reverse:
if bull:
if high[i] > hp:
hp = high[i]
af = min(af + iaf, maxaf)
if low[i - 1] < psar[i]:
psar[i] = low[i - 1]
if low[i - 2] < psar[i]:
psar[i] = low[i - 2]
else:
if low[i] < lp:
lp = low[i]
af = min(af + iaf, maxaf)
if high[i - 1] > psar[i]:
psar[i] = high[i - 1]
if high[i - 2] > psar[i]:
psar[i] = high[i - 2]
if bull:
psarbull[i] = psar[i]
else:
psarbear[i] = psar[i]
return {"dates":dates, "high":high, "low":low, "close":close, "psar":psar, "psarbear":psarbear, "psarbull":psarbull}
這段代碼有點問題 需要修改下才能使用
生成的dmp文件提示錯誤
ExceptionAddress: 7c812fd3 (kernel32+0x00012fd3)
ExceptionCode: c06d007f
ExceptionFlags: 00000000
NumberParameters: 1
Parameter[0]: 0012f7b0
執行 dds 0012f7b0
顯示:
0:000> dds 0012f7b0
0012f7b0 00000024
0012f7b4 038d96d4 libcef!_DELAY_IMPORT_DESCRIPTOR_dbghelp_dll
0012f7b8 039121b4 libcef!_imp__SymGetSearchPathW
0012f7bc 03678f30 libcef!_sz_dbghelp_dll
0012f7c0 00000001
0012f7c4 038d9de6 libcef!dxva2_NULL_THUNK_DATA_DLN+0x7e
0012f7c8 68d60000
DBGENG: dbghelp.dll - Partial symbol image load missing image info
DBGHELP: Module is not fully loaded into memory.
DBGHELP: Searching for symbols using debugger-provided data.
DBGHELP: e:\workspace\codes\pc2.0\build\release\dbghelp.pdb - file not found
DBGHELP: e:\workspace\codes\pc2.0\build\release\dll\dbghelp.pdb - file not found
DBGHELP: e:\workspace\codes\pc2.0\build\release\symbols\dll\dbghelp.pdb - file not found
DBGHELP: d:\2623\source\chromium\src\out\release\dbghelp.pdb - file not found
DBGHELP: d:\2623\source\chromium\src\out\release\dll\dbghelp.pdb - file not found
DBGHELP: d:\2623\source\chromium\src\out\release\symbols\dll\dbghelp.pdb - file not found
DBGHELP: dbghelp.pdb - file not found
*** WARNING: Unable to verify timestamp for dbghelp.dll
*** ERROR: Module load completed but symbols could not be loaded for dbghelp.dll
DBGHELP: dbghelp - no symbols loaded
dbghelp
0012f7cc 00000000
0012f7d0 0000007f
0012f7d4 038db314 libcef!dxva2_NULL_THUNK_DATA_DLN+0x15ac
0012f7d8 00000003
0012f7dc 00000000
0012f7e0 0012f890
0012f7e4 0233264b libcef!_tailMerge_dbghelp_dll+0xd
0012f7e8 0012f7b0
0012f7ec 039121b4 libcef!_imp__SymGetSearchPathW
0012f7f0 00000008
0012f7f4 7c9301db ntdll+0x101db
0012f7f8 00642f9e libcef!base::debug::`anonymous namespace'::InitializeSymbols+0x9e [d:\2623_\source\chromium\src\base\debug\stack_trace_win.cc @ 80]
0012f7fc ffffffff
0012f800 0017dbe0
0012f804 00000400
0012f808 00000006
0012f80c 00000000
0012f810 00000000
0012f814 00000000
0012f818 09193a78
0012f81c 0000037b
0012f820 00000128
0012f824 00000001
0012f828 77d193e9
為
SymGetSearchPathW函數找不到所致,文件為dbghelp.dll
使用更新后的dbghelp.dll替換后正常
這里以別人下載好的cef2623版本來編譯(默認支持mp3/h64)
網盤地址: https://pan.baidu.com/s/1jHY4hls
編譯先決條件:win64系統,安裝python2.7 Virtual Studio2013 硬盤空間大于54G以上
下載完成后解壓這里解壓到D盤下的2623目錄
打開CMD窗口執行以下操作以設定環境變量
Set
DEPOT_TOOLS_WIN_TOOLCHAIN=0
Set
CEF_USE_GN=0
Set
GYP_MSVS_VERSION=2013
Set GYP_GENERATORS=ninja,msvs-ninja
然后執行
python
automate-git.py --download-dir=e:\cef3\source --branch=2623 --no-update
--build-log-file --verbose-build --force-distrib --force-build
大致等待5個小時即可編譯完成
注意,這個指定—no-update 不更新代碼,如果不需要編譯debug版本,則需要指定
—no-debug-build
輸出目錄在src\cef\binary_distrib下
Cefclient.exe為demo程序,點擊并輸入www.html5test.com可查看支持音視頻的情況
當前編譯好的2623對音視頻的支持如下:
音視頻的支持有2處需要修改分別是
1是在source/chromium/src/cef/cef.gypi文件在variables節點下增加
'proprietary_codecs': 1,'ffmpeg_branding': 'Chrome',
2是修改
source\chromium\src\third_party\ffmpeg\chromium\config\Chrome\win\ia32\config.h
和source\chromium\src\third_party\ffmpeg\chromium\config\Chrome\win\x64\config.h
在宏FFMPEG_CONFIGURATION 中增加
–enable-decoder=’rv10,rv20,rv30,rv40,cook,h263,h263i,mpeg4,msmpeg4v1,msmpeg4v2,msmpeg4v3,amrnb,amrwb,ac3,flv’
–enable-demuxer=’rm,mpegvideo,avi,avisynth,h263,aac,amr,ac3,flv,mpegts,mpegtsraw’
–enable-parser=’mpegvideo,rv30,rv40,h263,mpeg4video,ac3
可以根據需要修改要支持的音視頻情況
摘要: QCustomPlot和QWt各有千秋前者偏輕,但是功能有點弱了,可以修改QCustomPlot增加Qwt的一些模塊和類如下 代碼為QComstomPlot使用QwtText的例子Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->class Q...
閱讀全文
class HTMLLayer : public QCPLayerable
{
Q_OBJECT
public:
HTMLLayer(QCustomPlot* plot);
~HTMLLayer();
public:
QString layerName()const;
void setVisible(bool visible);
void setHTML(const QString& html);
void setPen(const QPen& pen);
void setFont(const QFont& font);
protected:
virtual void applyDefaultAntialiasingHint(QCPPainter* painter)const;
virtual void draw(QCPPainter* painter);
private:
QPen mPen;
QFont mFont;
QTextDocument mDocument;
};
HTMLLayer::HTMLLayer(QCustomPlot* plot):
QCPLayerable(plot)
{
}
void HTMLLayer::setHTML(const QString& html)
{
mDocument.setHtml(html);
}
HTMLLayer::~HTMLLayer()
{
}
QString HTMLLayer::layerName()const
{
return "HtmlLayer";
}
void HTMLLayer::setVisible(bool visible)
{
QCPLayer* layer = mParentPlot->layer(layerName());
if(layer)
{
layer->setVisible(visible);
}
}
void HTMLLayer::setPen(const QPen& pen)
{
mPen = pen;
}
void HTMLLayer::setFont(const QFont& font)
{
mFont = font;
}
void HTMLLayer::applyDefaultAntialiasingHint(QCPPainter* painter)const
{
}
void HTMLLayer::draw(QCPPainter* painter)
{
painter->save();
QRectF rect = mParentPlot->rect();
painter->setPen(mPen);
painter->setFont(mFont);
painter->setAntialiasing(true);
QwtPainter::drawSimpleRichText(painter,rect,Qt::AlignLeft | Qt::AlignTop,mDocument);
painter->restore();
}
void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect,
int flags, const QTextDocument &text )
{
QTextDocument *txt = text.clone();
painter->save();
painter->setFont( txt->defaultFont() );
qwtUnscaleFont( painter );
txt->setDefaultFont( painter->font() );
txt->setPageSize( QSizeF( rect.width(), QWIDGETSIZE_MAX ) );
QAbstractTextDocumentLayout* layout = txt->documentLayout();
const double height = layout->documentSize().height();
double y = rect.y();
if ( flags & Qt::AlignBottom )
y += ( rect.height() - height );
else if ( flags & Qt::AlignVCenter )
y += ( rect.height() - height ) / 2;
QAbstractTextDocumentLayout::PaintContext context;
context.palette.setColor( QPalette::Text, painter->pen().color() );
painter->translate( rect.x(), y );
layout->draw( painter, context );
painter->restore();
delete txt;
}