#include "Draw.h" NAMESPACE_UPP #define LLOG(x) // LOG(x) #define LTIMING(x) // RTIMING(x) #ifdef PLATFORM_WIN32 static COLORREF sLightGray; void StaticExitDraw_() { Draw::FreeFonts(); } EXITBLOCK { StaticExitDraw_(); } #ifndef PLATFORM_WINCE void Add(LOGPALETTE *pal, int r, int g, int b) { pal->palPalEntry[pal->palNumEntries].peRed = min(r, 255); pal->palPalEntry[pal->palNumEntries].peGreen = min(g, 255); pal->palPalEntry[pal->palNumEntries].peBlue = min(b, 255); pal->palPalEntry[pal->palNumEntries++].peFlags = PC_NOCOLLAPSE; } HPALETTE GetQlibPalette() { static HPALETTE hQlibPalette; if(hQlibPalette) return hQlibPalette; Draw::InitColors(); LOGPALETTE *pal = (LOGPALETTE *) new byte[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)]; pal->palNumEntries = 0; pal->palVersion = 0x300; for(int r = 0; r < 6; r++) for(int g = 0; g < 6; g++) for(int b = 0; b < 6; b++) Add(pal, 255 * r / 5, 255 * g / 5, 255 * b / 5); for(int q = 0; q <= 16; q++) Add(pal, 16 * q, 16 * q, 16 * q); Add(pal, GetRValue(sLightGray), GetGValue(sLightGray), GetBValue(sLightGray)); hQlibPalette = CreatePalette(pal); delete[] pal; return hQlibPalette; } #endif Draw& GLOBAL_VP(ScreenDraw, ScreenInfo, (true)) HDC ScreenHDC() { return ScreenInfo(); } static bool _AutoPalette = true; bool Draw::AutoPalette() { return _AutoPalette; } void Draw::SetAutoPalette(bool ap) { _AutoPalette = ap; } COLORREF Draw::GetColor(Color c) const { COLORREF color = c; #ifdef PLATFORM_WINCE return color; #else if(!palette) return color; static Index *SColor; ONCELOCK { static Index StaticColor; StaticColor << RGB(0x00, 0x00, 0x00) << RGB(0x80, 0x00, 0x00) << RGB(0x00, 0x80, 0x00) << RGB(0x80, 0x80, 0x00) << RGB(0x00, 0x00, 0x80) << RGB(0x80, 0x00, 0x80) << RGB(0x00, 0x80, 0x80) << RGB(0xC0, 0xC0, 0xC0) << RGB(0xC0, 0xDC, 0xC0) << RGB(0xA6, 0xCA, 0xF0) << RGB(0xFF, 0xFB, 0xF0) << RGB(0xA0, 0xA0, 0xA4) << RGB(0x80, 0x80, 0x80) << RGB(0xFF, 0x00, 0x00) << RGB(0x00, 0xFF, 0x00) << RGB(0xFF, 0xFF, 0x00) << RGB(0x00, 0x00, 0xFF) << RGB(0xFF, 0x00, 0xFF) << RGB(0x00, 0xFF, 0xFF) << RGB(0xFF, 0xFF, 0xFF); SColor = &StaticColor; } if(color16 || !AutoPalette()) return GetNearestColor(handle, color); if(SColor->Find(color) >= 0) return color; if(color == sLightGray) return PALETTEINDEX(216 + 17); int r = GetRValue(color); int g = GetGValue(color); int b = GetBValue(color); return PALETTEINDEX(r == g && g == b ? (r + 8) / 16 + 216 : (r + 25) / 51 * 36 + (g + 25) / 51 * 6 + (b + 25) / 51); #endif } void Draw::InitColors() { } void Draw::SetColor(Color color) { DrawLock __; LLOG("SetColor " << color); if(color != lastColor) { LLOG("Setting, lastColor:" << FormatIntHex(lastColor.GetRaw()) << " color:" << FormatIntHex(color.GetRaw()) << " GetColor:" << FormatIntHex(GetColor(color)) << " palette:" << palette); HBRUSH oldBrush = actBrush; HBRUSH h; if(!IsNull(color)) h = (HBRUSH) SelectObject(handle, actBrush = CreateSolidBrush(GetColor(color))); else { HGDIOBJ empty = GetStockObject(HOLLOW_BRUSH); h = (HBRUSH) SelectObject(handle, empty); actBrush = NULL; } ASSERT(h); if(!orgBrush) orgBrush = h; if(oldBrush) DeleteObject(oldBrush); lastColor = color; } } void Draw::SetDrawPen(int width, Color color) { DrawLock __; if(IsNull(width)) width = PEN_NULL; if(width != lastPen || color != lastPenColor) { static int penstyle[] = { PS_NULL, PS_SOLID, PS_DASH, #ifndef PLATFORM_WINCE PS_DOT, PS_DASHDOT, PS_DASHDOTDOT #endif }; HPEN oldPen = actPen; actPen = CreatePen(width < 0 ? penstyle[-width - 1] : PS_SOLID, width < 0 ? 0 : width, GetColor(color)); HPEN h = (HPEN) SelectObject(handle, actPen); if(!orgPen) orgPen = h; if(oldPen) DeleteObject(oldPen); lastPen = width; lastPenColor = color; } } void Draw::SetOrg() { DrawLock __; #ifdef PLATFORM_WINCE ::SetViewportOrgEx(handle, actual_offset.x, actual_offset.y, 0); #else LLOG("Draw::SetOrg: clip = " << GetClip() << ", offset = " << actual_offset); ::SetWindowOrgEx(handle, -actual_offset.x, -actual_offset.y, 0); LLOG("//Draw::SetOrg: clip = " << GetClip()); #endif } #ifndef PLATFORM_WINCE Point Draw::LPtoDP(Point p) const { DrawLock __; ::LPtoDP(handle, p, 1); return p; } Point Draw::DPtoLP(Point p) const { DrawLock __; ::DPtoLP(handle, p, 1); return p; } Rect Draw::LPtoDP(const Rect& r) const { DrawLock __; Rect w = r; ::LPtoDP(handle, reinterpret_cast(&w), 2); return w; } Rect Draw::DPtoLP(const Rect& r) const { DrawLock __; Rect w = r; ::LPtoDP(handle, reinterpret_cast(&w), 2); return w; } #endif Size Draw::GetSizeCaps(int i, int j) const { DrawLock __; return Size(GetDeviceCaps(handle, i), GetDeviceCaps(handle, j)); } void Draw::LoadCaps() { DrawLock __; color16 = false; palette = (GetDeviceCaps(handle, RASTERCAPS) & RC_PALETTE); if(palette) color16 = GetDeviceCaps(handle, SIZEPALETTE) != 256; pagePixels = GetSizeCaps(HORZRES, VERTRES); pageMMs = GetSizeCaps(HORZSIZE, VERTSIZE); inchPixels = GetSizeCaps(LOGPIXELSX, LOGPIXELSY); sheetPixels = GetSizeCaps(PHYSICALWIDTH, PHYSICALHEIGHT); pageOffset = GetSizeCaps(PHYSICALOFFSETX, PHYSICALOFFSETY); is_mono = GetDeviceCaps(handle, BITSPIXEL) == 1 && GetDeviceCaps(handle, PLANES) == 1; /* if(!is_mono) { HBITMAP hbmp = (HBITMAP)GetCurrentObject(handle, OBJ_BITMAP); if(hbmp) { BITMAP bmp; GetObject(hbmp, sizeof(bmp), &bmp); is_mono = bmp.bmPlanes == 1 && bmp.bmBitsPixel == 1; } } */ } void Draw::SetDevice(const char *s) { DrawLock __; static Index map; device = map.FindAdd(s) + 1; LoadCaps(); } void Draw::Cinit() { DrawLock __; lastColor = Color::FromCR(COLORREF(-5)); lastPenColor = Color::FromCR(COLORREF(-5)); lastTextColor = COLORREF(-1); lastPen = Null; actBrush = orgBrush = NULL; actPen = orgPen = NULL; orgFont = NULL; lastFont.Clear(); } void Draw::Init() { DrawLock __; Cinit(); SetBkMode(handle, TRANSPARENT); ::SetTextAlign(handle, TA_BASELINE); #ifdef PLATFORM_WINCE actual_offset = Point(0, 0); #else ::GetViewportOrgEx(handle, actual_offset); #endif LoadCaps(); } void Draw::Reset() { DrawLock __; device = 0; pixels = true; printer = aborted = backdraw = is_mono = false; } Draw::Draw() { DrawLock __; InitColors(); InitFonts(); actual_offset = Point(0, 0); Reset(); handle = NULL; } Draw::Draw(HDC hdc) { DrawLock __; InitColors(); InitFonts(); Reset(); Attach(hdc); } void Draw::Unselect0() { DrawLock __; if(orgPen) SelectObject(handle, orgPen); if(orgBrush) SelectObject(handle, orgBrush); if(orgFont) SelectObject(handle, orgFont); if(actPen) DeleteObject(actPen); if(actBrush) DeleteObject(actBrush); Cinit(); } void Draw::Unselect() { DrawLock __; while(cloff.GetCount()) End(); Unselect0(); } Draw::~Draw() { DrawLock __; if(handle) Unselect(); } HDC Draw::BeginGdi() { DrawLock __; Begin(); return handle; } void Draw::EndGdi() { DrawLock __; Unselect0(); End(); } NilDraw::NilDraw() { DrawLock __; Attach(ScreenInfo().GetHandle()); pixels = false; cloff.Clear(); } NilDraw::~NilDraw() { DrawLock __; Detach(); } void BackDraw::Create(Draw& w, int cx, int cy) { ASSERT(w.GetHandle()); DrawLock __; Destroy(); size.cx = cx; size.cy = cy; hbmp = ::CreateCompatibleBitmap(w.GetHandle(), cx, cy); handle = ::CreateCompatibleDC(w.GetHandle()); ASSERT(hbmp); ASSERT(handle); #ifndef PLATFORM_WINCE if(w.PaletteMode() && AutoPalette()) { ::SelectPalette(handle, GetQlibPalette(), FALSE); ::RealizePalette(handle); } #endif hbmpold = (HBITMAP) ::SelectObject(handle, hbmp); Init(); backdraw = true; } void BackDraw::Put(Draw& w, int x, int y) { DrawLock __; ASSERT(handle); LTIMING("BackDraw::Put"); #ifdef PLATFORM_WINCE ::SetViewportOrgEx(handle, 0, 0, 0); #else ::SetWindowOrgEx(handle, 0, 0, NULL); #endif ::BitBlt(w, x, y, size.cx, size.cy, *this, 0, 0, SRCCOPY); } void BackDraw::Destroy() { DrawLock __; if(handle) { Unselect(); ::SelectObject(handle, hbmpold); ::DeleteDC(handle); ::DeleteObject(hbmp); handle = NULL; } } ScreenDraw::ScreenDraw(bool ic) { DrawLock __; #ifdef PLATFORM_WINCE Attach(CreateDC(NULL, NULL, NULL, NULL)); #else Attach((ic ? CreateIC : CreateDC)("DISPLAY", NULL, NULL, NULL)); if(PaletteMode() && AutoPalette()) { SelectPalette(handle, GetQlibPalette(), TRUE); RealizePalette(handle); } #endif } ScreenDraw::~ScreenDraw() { DrawLock __; Unselect(); DeleteDC(handle); } #ifndef PLATFORM_WINCE void PrintDraw::InitPrinter() { DrawLock __; Init(); printer = true; pixels = false; ::SetMapMode(handle, MM_ANISOTROPIC); ::SetViewportExtEx(handle, inchPixels.cx, inchPixels.cy, NULL); ::SetViewportOrgEx(handle, 0, 0, NULL); ::SetWindowExtEx(handle, 600, 600, NULL); ::SetWindowOrgEx(handle, 0, 0, NULL); actual_offset = Point(0, 0); } void PrintDraw::StartPage() { DrawLock __; if(IsAborted()) return; Unselect(); if(::StartPage(handle) <= 0) Abort(); else InitPrinter(); } void PrintDraw::EndPage() { DrawLock __; if(IsAborted()) return; Unselect(); ASSERT(printer); if(::EndPage(handle) <= 0) Abort(); } PrintDraw::PrintDraw(HDC hdc, const char *docname) : Draw(hdc) { DrawLock __; DOCINFO di; memset(&di, 0, sizeof(di)); di.cbSize = sizeof(di); String sys_docname = ToSystemCharset(docname); di.lpszDocName = ~sys_docname; if(::StartDoc(hdc, &di) <= 0) { Abort(); return; } InitPrinter(); } PrintDraw::~PrintDraw() { DrawLock __; if(IsAborted()) ::AbortDoc(handle); else ::EndDoc(handle); DeleteDC(handle); handle = NULL; } #endif #endif END_UPP_NAMESPACE