bool IGraphics::DrawRotatedMask(IBitmap* pIBase, IBitmap* pIMask, IBitmap* pITop, int x, int y, double angle, const IChannelBlend* pBlend) { LICE_IBitmap* pBase = (LICE_IBitmap*) pIBase->mData; LICE_IBitmap* pMask = (LICE_IBitmap*) pIMask->mData; LICE_IBitmap* pTop = (LICE_IBitmap*) pITop->mData; double dA = angle * PI / 180.0; int W = pIBase->W; int H = pIBase->H; // RECT srcR = { 0, 0, W, H }; float xOffs = (W % 2 ? -0.5f : 0.0f); if (!mTmpBitmap) { mTmpBitmap = new LICE_MemBitmap(); } _LICE::LICE_Copy(mTmpBitmap, pBase); _LICE::LICE_ClearRect(mTmpBitmap, 0, 0, W, H, LICE_RGBA(255, 255, 255, 0)); _LICE::LICE_RotatedBlit(mTmpBitmap, pMask, 0, 0, W, H, 0.0f, 0.0f, (float) W, (float) H, (float) dA, true, 1.0f, LICE_BLIT_MODE_ADD | LICE_BLIT_FILTER_BILINEAR | LICE_BLIT_USE_ALPHA, xOffs, 0.0f); _LICE::LICE_RotatedBlit(mTmpBitmap, pTop, 0, 0, W, H, 0.0f, 0.0f, (float) W, (float) H, (float) dA, true, 1.0f, LICE_BLIT_MODE_COPY | LICE_BLIT_FILTER_BILINEAR | LICE_BLIT_USE_ALPHA, xOffs, 0.0f); IRECT r = IRECT(x, y, x + W, y + H).Intersect(&mDrawRECT); _LICE::LICE_Blit(mDrawBitmap, mTmpBitmap, r.L, r.T, r.L - x, r.T - y, r.R - r.L, r.B - r.T, LiceWeight(pBlend), LiceBlendMode(pBlend)); // ReaperExt::LICE_Blit(mDrawBitmap, mTmpBitmap, x, y, &srcR, LiceWeight(pBlend), LiceBlendMode(pBlend)); return true; }
void SNM_DynSizedText::DrawLines(LICE_IBitmap* _drawbm, RECT* _r, int _fontHeight) { if (!m_font.GetHFont() || m_lastFontH<=0) return; RECT tr; tr.top = _r->top + int((_r->bottom-_r->top)/2.0 - (_fontHeight*m_lines.GetSize())/2.0 + 0.5); tr.left = _r->left; tr.right = _r->right; for (int i=0; i < m_lines.GetSize(); i++) { tr.bottom = tr.top+_fontHeight; #ifdef _SNM_DYN_FONT_DEBUG LICE_DrawRect(_drawbm, tr.left, tr.top, tr.right, tr.bottom, LICE_RGBA(255,255,255,255)); #endif m_font.DrawText( _drawbm, m_lines.Get(i)->Get(), -1, &tr, // DT_BOTTOM to avoid cropped display (issue 606) m_align | (m_alpha<255 ? (DT_SINGLELINE|DT_NOPREFIX|DT_BOTTOM|LICE_DT_USEFGALPHA|LICE_DT_NEEDALPHA) : DT_SINGLELINE|DT_NOPREFIX|DT_BOTTOM) ); tr.top = tr.bottom; } }
void FindWnd::OnInitDlg() { m_resize.init_item(IDC_EDIT, 0.0, 0.0, 1.0, 0.0); SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_EDIT), GWLP_USERDATA, 0xdeadf00b); // load prefs m_type = GetPrivateProfileInt(FIND_INI_SEC, "Type", 0, g_SNM_IniFn.Get()); m_zoomSrollItems = (GetPrivateProfileInt(FIND_INI_SEC, "ZoomScrollToFoundItems", 0, g_SNM_IniFn.Get()) == 1); LICE_CachedFont* font = SNM_GetThemeFont(); m_vwnd_painter.SetGSC(WDL_STYLE_GetSysColor); m_parentVwnd.SetRealParent(m_hwnd); m_txtScope.SetID(TXTID_SCOPE); m_txtScope.SetFont(font); m_txtScope.SetText(__LOCALIZE("Find in:","sws_DLG_154")); m_parentVwnd.AddChild(&m_txtScope); m_btnEnableZommScroll.SetID(BTNID_ZOOM_SCROLL_EN); m_btnEnableZommScroll.SetTextLabel(__LOCALIZE("Zoom/Scroll","sws_DLG_154"), -1, font); m_btnEnableZommScroll.SetCheckState(m_zoomSrollItems); m_parentVwnd.AddChild(&m_btnEnableZommScroll); m_btnFind.SetID(BTNID_FIND); m_parentVwnd.AddChild(&m_btnFind); m_btnPrev.SetID(BTNID_PREV); m_parentVwnd.AddChild(&m_btnPrev); m_btnNext.SetID(BTNID_NEXT); m_parentVwnd.AddChild(&m_btnNext); m_cbType.SetID(CMBID_TYPE); m_cbType.SetFont(font); m_cbType.AddItem(__LOCALIZE("Item names","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Item names (all takes)","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Media filenames","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Media filenames (all takes)","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Item notes","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Track names","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Track notes","sws_DLG_154")); m_cbType.AddItem(__LOCALIZE("Marker/region names","sws_DLG_154")); m_cbType.SetCurSel(m_type); m_parentVwnd.AddChild(&m_cbType); m_txtResult.SetID(TXTID_RESULT); m_txtResult.SetFont(font); m_txtResult.SetColors(LICE_RGBA(170,0,0,255)); m_parentVwnd.AddChild(&m_txtResult); g_notFound = false; // *g_searchStr = 0; SetDlgItemText(m_hwnd, IDC_EDIT, g_searchStr); m_parentVwnd.RequestRedraw(NULL); }
void LICE_TexGen_CircNoise(LICE_IBitmap *dest, RECT *rect, float rv, float gv, float bv, float nrings, float power, int size) { initNoise(); int span=dest->getRowSpan(); int w = dest->getWidth(); int h = dest->getHeight(); int x = 0; int y = 0; if(rect) { x = rect->left; y = rect->top; w = rect->right - rect->left; h = rect->bottom - rect->top; } if (x<0) { w+=x; x=0; } if (y<0) { h+=y; y=0; } if (x+w > dest->getWidth()) w=dest->getWidth()-x; if (y+h > dest->getHeight()) h=dest->getHeight()-y; if (w<1 || h<1) return; LICE_pixel *startp = dest->getBits(); if (dest->isFlipped()) { startp += x + (dest->getHeight()-1-y)*span; span=-span; } else startp += x + y*span; float xyPeriod = nrings; float turbPower = power; const float iturbSize = 1.0f/(float)size; const float turbSize = (float)size; { LICE_pixel *p = startp; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { float xValue = ((float)j - w / 2) / w; float yValue = ((float)i - h / 2) / h; float distValue = sqrt(xValue * xValue + yValue * yValue) + turbPower * turbulence(j, i, turbSize, iturbSize) / 256.0f; float col = (float)fabs(256.0 * sin(2 * xyPeriod * distValue * 3.14159)); p[j] = LICE_RGBA((int)(col*rv),(int)(col*bv),(int)(col*gv),255); } p+=span; } } }
void SNM_TinyLeftButton::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect) { RECT r = m_position; r.left += origin_x; r.right += origin_x; r.top += origin_y; r.bottom += origin_y; ColorTheme* ct = SNM_GetColorTheme(); int col = ct ? LICE_RGBA_FROMNATIVE(ct->main_text,255) : LICE_RGBA(255,255,255,255); float alpha = m_en ? 0.8f : 0.4f; LICE_FillTriangle(drawbm, r.right-1, r.top, r.left, r.top+int((r.bottom-r.top)/2 +0.5), r.right-1, r.bottom-1, col, alpha); // borders needed (the above ^^ draws w/o aa) LICE_Line(drawbm, r.right-1, r.top, r.left, r.top+int((r.bottom-r.top)/2 +0.5), col, alpha, 0, true); LICE_Line(drawbm, r.left, r.top+int((r.bottom-r.top)/2 +0.5), r.right-1, r.bottom-1, col, alpha, 0, true); LICE_Line(drawbm, r.right-1, r.bottom-1, r.right-1, r.top, col, alpha, 0, true); }
std::shared_ptr<LiceControl> create_licecontrol(ReaScriptWindow* w, std::string classname) { if (classname == "BreakpointEnvelope") { auto points = std::make_shared<breakpoint_envelope>("Untitled envelope",LICE_RGBA(0,255,0,255)); points->add_point({ 0.0,0.5 }, false); points->add_point({ 1.0,0.5 }, false); points->sort_points(); auto control = std::make_shared<EnvelopeControl>(w); control->add_envelope(points); // By default, don't set the control dirty on envelope point drag control->setIntegerProperty(2, 0); return control; } if (classname == "ZoomScrollBar") { auto zsb = std::make_shared<ZoomScrollBar>(w); return zsb; } return nullptr; }
void SNM_TinyTickBox::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect) { RECT r = m_position; r.left += origin_x; r.right += origin_x; r.top += origin_y; r.bottom += origin_y; ColorTheme* ct = SNM_GetColorTheme(); int col = ct ? LICE_RGBA_FROMNATIVE(ct->main_text,255) : LICE_RGBA(255,255,255,255); float alpha = m_en ? 0.8f : 0.4f; // border LICE_Line(drawbm,r.left,r.bottom-1,r.left,r.top,col,alpha,0,false); LICE_Line(drawbm,r.left,r.top,r.right-1,r.top,col,alpha,0,false); LICE_Line(drawbm,r.right-1,r.top,r.right-1,r.bottom-1,col,alpha,0,false); LICE_Line(drawbm,r.left,r.bottom-1,r.right-1,r.bottom-1,col,alpha,0,false); if (m_checkstate) LICE_FillRect(drawbm, r.left+2, r.top+2, r.right-r.left-4, r.bottom-r.top-4, col, alpha); }
void OnPaintPlusOrMinus(RECT *_position, bool _en, bool _plus, LICE_IBitmap* _drawbm, int _origin_x, int _origin_y, RECT* _cliprect) { RECT r = *_position; r.left += _origin_x; r.right += _origin_x; r.top += _origin_y; r.bottom += _origin_y; ColorTheme* ct = SNM_GetColorTheme(); int col = ct ? LICE_RGBA_FROMNATIVE(ct->main_text,255) : LICE_RGBA(255,255,255,255); float alpha = _en ? 0.8f : 0.4f; // border LICE_Line(_drawbm,r.left,r.bottom-1,r.left,r.top,col,alpha,0,false); LICE_Line(_drawbm,r.left,r.top,r.right-1,r.top,col,alpha,0,false); LICE_Line(_drawbm,r.right-1,r.top,r.right-1,r.bottom-1,col,alpha,0,false); LICE_Line(_drawbm,r.left,r.bottom-1,r.right-1,r.bottom-1,col,alpha,0,false); // + or - int delta = _plus ? 2:3; LICE_Line(_drawbm,r.left+delta,int(r.top+((r.bottom-r.top)/2)+0.5),r.right-(delta+1),int(r.top+((r.bottom-r.top)/2)+0.5),col,alpha,0,false); if (_plus) LICE_Line(_drawbm,int(r.left+((r.right-r.left)/2)+0.5), r.top+delta,int(r.left+((r.right-r.left)/2)+0.5),r.bottom-(delta+1),col,alpha,0,false); }
void WDL_VirtualIconButton_PreprocessSkinConfig(WDL_VirtualIconButton_SkinConfig *a) { if (a && a->image) { a->image_ltrb_used.flags=0; int wi; for(wi=0;wi<2;wi++) { LICE_IBitmap *srcimg = wi ? a->image : a->olimage; if (!srcimg) continue; int w=srcimg->getWidth(); int h=srcimg->getHeight(); if (LICE_GetPixel(srcimg,0,0)==LICE_RGBA(255,0,255,255)&& LICE_GetPixel(srcimg,w-1,h-1)==LICE_RGBA(255,0,255,255)) { int lext=0,rext=0,bext=0,text=0; int x; for (x = 1; x < w/3 && LICE_GetPixel(srcimg,x,0)==LICE_RGBA(255,0,255,255); x ++); lext=x-1; for (x = 1; x < h && LICE_GetPixel(srcimg,0,x)==LICE_RGBA(255,0,255,255); x ++); text=x-1; for (x = w-2; x >= (w*2/3) && LICE_GetPixel(srcimg,x,h-1)==LICE_RGBA(255,0,255,255); x --); rext=w-2-x; for (x = h-2; x >= text && LICE_GetPixel(srcimg,w-1,x)==LICE_RGBA(255,0,255,255); x --); bext=h-2-x; if (lext||text||rext||bext) { a->image_ltrb_used.flags |= 1 << wi; short *buf = wi ? a->image_ltrb_main : a->image_ltrb_ol; buf[0]=lext; buf[1]=text; buf[2]=rext; buf[3]=bext; } } } } }
void SNM_DynSizedText::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect) { RECT r = m_position; r.left += origin_x; r.right += origin_x; r.top += origin_y; r.bottom += origin_y; int h = r.bottom-r.top; int w = r.right-r.left; ColorTheme* ct = SNM_GetColorTheme(); int col = m_col; if (!col) col = ct ? LICE_RGBA_FROMNATIVE(ct->main_text, m_alpha) : LICE_RGBA(255,255,255,255); if (m_wantBorder) LICE_DrawRect(drawbm,r.left,r.top,w,h,col,0.2f); // title lane int laneHeight = GetTitleLaneHeight(); if (WantTitleLane() && HasTitleLane()) { if (m_wantBorder) LICE_Line(drawbm, r.left,r.top+laneHeight-1,r.right,r.top+laneHeight-1,col,0.2f); // title's band coloring (works for all themes) LICE_FillRect(drawbm,r.left,r.top,r.right-r.left,laneHeight,col,1.0f,LICE_BLIT_MODE_OVERLAY); LICE_FillRect(drawbm,r.left,r.top,r.right-r.left,laneHeight,col,1.0f,LICE_BLIT_MODE_OVERLAY); static LICE_CachedFont sFont; if (!sFont.GetHFont()) // single lazy init.. { LOGFONT lf = { SNM_FONT_HEIGHT, 0,0,0,FW_BOLD,FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,SNM_FONT_NAME }; sFont.SetFromHFont(CreateFontIndirect(&lf),LICE_FONT_FLAG_OWNS_HFONT|LICE_FONT_FLAG_FORCE_NATIVE); // others props are set on demand (support theme switches) } sFont.SetBkMode(TRANSPARENT); sFont.SetTextColor(LICE_RGBA_FROMNATIVE(WDL_STYLE_GetSysColor(COLOR_WINDOW), 255)); // "negative" color { RECT tr = {r.left,r.top,r.right,r.top+laneHeight}; char buf[64] = ""; _snprintfSafe(buf, sizeof(buf), " %s ", m_title.Get()); // trick for better display when left/right align sFont.DrawText(drawbm, buf, -1, &tr, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|m_titleAlign); } // resize draw rect: take band into account r.top += laneHeight; h = r.bottom-r.top; } // ok, now the meat: render lines with a dynamic sized text if (!m_lines.GetSize() || !m_lines.Get(m_maxLineIdx)) return; /////////////////////////////////////////////////////////////////////////////// #ifndef _SNM_MISC // 1st sol.: full width but several fonts can be tried // initial font height estimation // touchy: the better estimation, the less cpu use! int estimFontH = int((w*2.65)/m_lines.Get(m_maxLineIdx)->GetLength()); // 2.65 = average from tests.. if (estimFontH > int(h/m_lines.GetSize())+0.5) estimFontH = int(h/m_lines.GetSize()+0.5); // check if the current font can do the job if (m_lastFontH>=SNM_FONT_HEIGHT && abs(estimFontH-m_lastFontH) < 2) // tolerance: 2 pixels { #ifdef _SNM_DYN_FONT_DEBUG OutputDebugString("SNM_DynSizedText::OnPaint() - Skip font creation\n"); #endif m_font.SetTextColor(col); DrawLines(drawbm, &r, m_lastFontH); } else { m_lastFontH = estimFontH; #ifdef _SNM_DYN_FONT_DEBUG int dbgTries=0; #endif while(m_lastFontH>SNM_FONT_HEIGHT) { HFONT lf = CreateFont(m_lastFontH,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,m_fontName.Get()); m_font.SetFromHFont(lf, LICE_FONT_FLAG_OWNS_HFONT|LICE_FONT_FLAG_FORCE_NATIVE); m_font.SetBkMode(TRANSPARENT); m_font.SetTextColor(col); RECT tr = {0,0,0,0}; // DT flags must be consistent with DrawLines() m_font.DrawText(NULL, m_lines.Get(m_maxLineIdx)->Get(), -1, &tr, DT_SINGLELINE|DT_BOTTOM|DT_NOPREFIX|DT_CALCRECT); if ((tr.right - tr.left) > (w-int(w*0.02+0.5))) // room: 2% of w { m_font.SetFromHFont(NULL,LICE_FONT_FLAG_OWNS_HFONT); DeleteObject(lf); m_lastFontH--; #ifdef _SNM_DYN_FONT_DEBUG dbgTries++; #endif } else { DrawLines(drawbm, &r, m_lastFontH); // no font deletion: will try to re-use it.. break; } } #ifdef _SNM_DYN_FONT_DEBUG char dbg[256]; _snprintfSafe(dbg, sizeof(dbg), "SNM_DynSizedText::OnPaint() - %d tries, estim: %d, real: %d\n", dbgTries, estimFontH, m_lastFontH); OutputDebugString(dbg); #endif } /////////////////////////////////////////////////////////////////////////////// #else // 2nd sol.: render text in best effort, single font creation /*JFB commented: truncated text.. int fontHeight = int((w*2.65)/m_lines.Get(m_maxLineIdx)->GetLength()); // 2.65 = average from tests.. if (fontHeight > int(h/m_lines.GetSize())+0.5) fontHeight = int(h/m_lines.GetSize()+0.5); */ // font height estimation (safe but it does not use all the available width/height) int fontHeight = int(h/m_lines.GetSize() + 0.5); while (fontHeight>SNM_FONT_HEIGHT && (fontHeight*m_lines.Get(m_maxLineIdx)->GetLength()*0.55) > w) // 0.55: h/w factor fontHeight--; if (fontHeight>=SNM_FONT_HEIGHT) { HFONT lf = CreateFont(fontHeight,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,m_fontName.Get()); m_font.SetFromHFont(lf, LICE_FONT_FLAG_OWNS_HFONT|LICE_FONT_FLAG_FORCE_NATIVE); m_font.SetBkMode(TRANSPARENT); m_font.SetTextColor(col); DrawLines(drawbm, &r, fontHeight); m_font.SetFromHFont(NULL,LICE_FONT_FLAG_OWNS_HFONT); DeleteObject(lf); } #endif }
void WDL_VirtualSlider::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect) { origin_x += m_position.left; // convert drawing origin to local coords origin_y += m_position.top; bool isVert = GetIsVert(); int rsize=m_maxr-m_minr; if (rsize<1)rsize=1; int viewh=m_position.bottom-m_position.top; int vieww=m_position.right-m_position.left; WDL_VirtualWnd_BGCfg *back_image=m_skininfo && m_skininfo->bgimagecfg[isVert].bgimage ? &m_skininfo->bgimagecfg[isVert] : 0; LICE_IBitmap *bm_image=m_skininfo ? m_skininfo->thumbimage[isVert] : 0; int bm_w=16,bm_h=16,bm_w2=16,bm_h2=16; int imgoffset=0; HBITMAP bm=0; bool wantKnob=false; if (bm_image) { bm_w2=bm_w=bm_image->getWidth(); bm_h2=bm_h=bm_image->getHeight(); AdjustThumbImageSize(vieww,viewh,m_skininfo,isVert,&bm_w2,&bm_h2,&imgoffset,&wantKnob,m_knobbias); } else { bm_image=WDL_STYLE_GetSliderBitmap2(isVert); if (bm_image) { bm_w2=bm_w=bm_image->getWidth(); bm_h2=bm_h=bm_image->getHeight(); } AdjustThumbImageSize(vieww,viewh,NULL,isVert,&bm_w2,&bm_h2,&imgoffset,&wantKnob,m_knobbias); } float alpha = (m_grayed ? 0.25f : 1.0f); m_is_knob = wantKnob; if (isVert||wantKnob) { int pos = ((m_maxr-m_pos)*(viewh-bm_h2))/rsize; //viewh - bm_h2 - ((m_pos-m_minr) * (viewh - bm_h2))/rsize; if (wantKnob) { int sz= min(vieww,viewh); origin_x += (vieww-sz)/2; origin_y += (viewh-sz)/2; vieww = viewh = sz; back_image = m_knobbg[sz>28]; if (back_image && !back_image->bgimage) back_image=NULL; } if (back_image) { WDL_VirtualWnd_ScaledBlitBG(drawbm,back_image, origin_x,origin_y,vieww,viewh, origin_x,origin_y,vieww,viewh, 1.0f,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR|LICE_BLIT_USE_ALPHA); if (m_bgcol1_msg) { int brcol=-100; SendCommand(m_bgcol1_msg,(INT_PTR)&brcol,GetID(),this); if (brcol != -100) { static LICE_MemBitmap tmpbm;//not threadsafe tmpbm.resize(vieww,viewh); WDL_VirtualWnd_ScaledBlitBG(&tmpbm,back_image,0,0,vieww,viewh, 0,0,vieww,viewh,1.0f,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR); LICE_ClearRect(&tmpbm,0,0,vieww,viewh,LICE_RGBA(0,0,0,255),LICE_RGBA(GetRValue(brcol),GetGValue(brcol),GetBValue(brcol),0)); RECT r={0,0,vieww,viewh}; LICE_Blit(drawbm,&tmpbm,origin_x,origin_y,&r,0.5,LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA); } } } if (!wantKnob) { int zlc = m_zl_color; if (!zlc && m_skininfo) zlc = m_skininfo->zeroline_color; if (!back_image || zlc) { int center=m_center; if (center < 0) center=WDL_STYLE_GetSliderDynamicCenterPos(); int y=((m_maxr-center)*(viewh-bm_h2))/rsize + ((bm_h-1)/2-imgoffset); if (!zlc) zlc = LICE_RGBA_FROMNATIVE(GSC(COLOR_BTNTEXT),255); LICE_Line(drawbm,origin_x+2,origin_y+y,origin_x+vieww-2,origin_y+y, zlc, LICE_GETA(zlc)/255.0, LICE_BLIT_MODE_COPY,false); } if (!back_image) { LICE_pixel fgcol = GSC(COLOR_3DHILIGHT); fgcol = LICE_RGBA_FROMNATIVE(fgcol,255); LICE_pixel bgcol=GSC(COLOR_3DSHADOW); if (m_bgcol1_msg) SendCommand(m_bgcol1_msg,(INT_PTR)&bgcol,GetID(),this); bgcol = LICE_RGBA_FROMNATIVE(bgcol,255); int offs= (vieww - 4)/2; // white with black border, mmm RECT r={origin_x + offs,origin_y + bm_h2/3, origin_x + offs + 5,origin_y + viewh - bm_h2/3}; LICE_FillRect(drawbm,r.left+1,r.top+1, r.right-r.left-2,r.bottom-r.top-2,bgcol,1.0f,LICE_BLIT_MODE_COPY); LICE_Line(drawbm,r.left+1,r.top,r.right-2,r.top,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.left+1,r.bottom-1,r.right-2,r.bottom-1,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.left,r.top+1,r.left,r.bottom-2,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.right-1,r.top+1,r.right-1,r.bottom-2,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); } if (bm_image) { int ypos=origin_y+pos-imgoffset; int xpos=origin_x; RECT r={0,0,bm_w2,bm_h}; /* if (vieww<bm_w) { r.left=(bm_w-vieww)/2; r.right=r.left+vieww; } else */ xpos+=(vieww-bm_w2)/2; m_tl_extra=origin_y-ypos; if (m_tl_extra<0)m_tl_extra=0; m_br_extra=ypos+(r.bottom-r.top) - (origin_y+m_position.bottom-m_position.top); if (m_br_extra<0)m_br_extra=0; LICE_Blit(drawbm,bm_image,xpos,ypos,&r,alpha,LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA); } } else { LICE_pixel col = m_knob_color ? m_knob_color : LICE_RGBA_FROMNATIVE(GSC(COLOR_3DHILIGHT),255); float alpha = LICE_GETA(col)/255.0f; int cx=origin_x+vieww/2; int cy=origin_y+viewh/2; float rd = vieww/2-4 + m_knob_lineextrasize; float r2=rd*0.125f; if (!back_image) LICE_Circle(drawbm, cx, cy, rd, col, alpha, LICE_BLIT_MODE_COPY, true); float val; int center=m_center; if (center < 0) center=WDL_STYLE_GetSliderDynamicCenterPos(); if (center > m_minr && (m_pos < center || center >= m_maxr)) val = (m_pos-center) / (double)(center-m_minr); else val = (m_pos-center) / (double)(m_maxr-center); #define KNOBANGLE_MAX (3.14159*7.0/8.0); float a = val*KNOBANGLE_MAX; float sina=sin(a); float cosa=cos(a); float x1=cx+r2*sina; float y1=cy-r2*cosa; float x2=cx+rd*sina; float y2=cy-rd*cosa; LICE_FLine(drawbm, x1, y1, x2, y2, col, alpha, LICE_BLIT_MODE_COPY, true); } } else { int pos = ((m_pos-m_minr) * (vieww - bm_w2))/rsize; if (back_image) { WDL_VirtualWnd_ScaledBlitBG(drawbm,back_image, origin_x,origin_y,vieww,viewh, origin_x,origin_y,vieww,viewh, 1.0,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR|LICE_BLIT_USE_ALPHA); // blit, tint color too? if (m_bgcol1_msg) { int brcol=-100; SendCommand(m_bgcol1_msg,(INT_PTR)&brcol,GetID(),this); if (brcol != -100) { static LICE_MemBitmap tmpbm; //not threadsafe tmpbm.resize(vieww,viewh); WDL_VirtualWnd_ScaledBlitBG(&tmpbm,back_image,0,0,vieww,viewh, 0,0,vieww,viewh,1.0,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR); LICE_ClearRect(&tmpbm,0,0,vieww,viewh,LICE_RGBA(0,0,0,255),LICE_RGBA(GetRValue(brcol),GetGValue(brcol),GetBValue(brcol),0)); RECT r={0,0,vieww,viewh}; LICE_Blit(drawbm,&tmpbm,origin_x,origin_y,&r,0.5,LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA); } } } int zlc = m_zl_color; if (!zlc && m_skininfo) zlc = m_skininfo->zeroline_color; if (!back_image || zlc) { int center=m_center; if (center < 0) center=WDL_STYLE_GetSliderDynamicCenterPos(); int x=((center-m_minr)*(vieww-bm_w2))/rsize + bm_w/2 - imgoffset; if (!zlc) zlc = LICE_RGBA_FROMNATIVE(GSC(COLOR_BTNTEXT),255); LICE_Line(drawbm,origin_x+x,origin_y+2,origin_x+x,origin_y+viewh-2, zlc, LICE_GETA(zlc)/255.0, LICE_BLIT_MODE_COPY,false); } if (!back_image) { LICE_pixel fgcol = GSC(COLOR_3DHILIGHT); fgcol = LICE_RGBA_FROMNATIVE(fgcol,255); LICE_pixel bgcol=GSC(COLOR_3DSHADOW); if (m_bgcol1_msg) SendCommand(m_bgcol1_msg,(INT_PTR)&bgcol,GetID(),this); bgcol = LICE_RGBA_FROMNATIVE(bgcol,255); int offs= (viewh - 4)/2; // white with black border, mmm RECT r={origin_x + bm_w2/3,origin_y + offs, origin_x + vieww - bm_w2/3,origin_y + offs + 5}; LICE_FillRect(drawbm,r.left+1,r.top+1, r.right-r.left-2,r.bottom-r.top-2,bgcol,1.0f,LICE_BLIT_MODE_COPY); LICE_Line(drawbm,r.left+1,r.top,r.right-2,r.top,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.left+1,r.bottom-1,r.right-2,r.bottom-1,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.left,r.top+1,r.left,r.bottom-2,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.right-1,r.top+1,r.right-1,r.bottom-2,fgcol,1.0f,LICE_BLIT_MODE_COPY,false); } if (bm_image) { int xpos=origin_x+pos-imgoffset; int ypos=origin_y; RECT r={0,0,bm_w,bm_h2}; /*if (viewh<bm_h) { r.top=(bm_h-viewh)/2; r.bottom=r.top+viewh; } else */ ypos+=(viewh-bm_h2)/2; m_tl_extra=origin_x-xpos; if (m_tl_extra<0)m_tl_extra=0; m_br_extra=xpos+(r.right-r.left) - (origin_x+m_position.right-m_position.left); if (m_br_extra<0)m_br_extra=0; /* if (xpos < origin_x) { r.left += (origin_x-xpos); xpos=origin_x; } if (xpos+(r.right-r.left) > origin_x+m_position.right-m_position.left) r.right = origin_x+m_position.right-m_position.left - (xpos-r.left); */ LICE_Blit(drawbm,bm_image,xpos,ypos,&r,alpha,LICE_BLIT_MODE_COPY|LICE_BLIT_USE_ALPHA); } } }
LICE_IBitmap *LICE_LoadJPG(const char *filename, LICE_IBitmap *bmp) { struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr={{0},}; JSAMPARRAY buffer; int row_stride; FILE *fp=NULL; #ifdef _WIN32 if (GetVersion()<0x80000000) { WCHAR wf[2048]; if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048)) fp = _wfopen(wf,L"rb"); } #endif if (!fp) fp = fopen(filename,"rb"); if (!fp) return 0; jerr.pub.error_exit = LICEJPEG_Error; jerr.pub.emit_message = LICEJPEG_EmitMsg; jerr.pub.output_message = LICEJPEG_OutMsg; jerr.pub.format_message = LICEJPEG_FmtMsg; jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr; cinfo.err = &jerr.pub; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); fclose(fp); return 0; } jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); if (bmp) { bmp->resize(cinfo.output_width,cinfo.output_height); if (bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); return 0; } } else bmp=new LICE_MemBitmap(cinfo.output_width,cinfo.output_height); LICE_pixel *bmpptr = bmp->getBits(); int dbmpptr=bmp->getRowSpan(); if (bmp->isFlipped()) { bmpptr += dbmpptr*(bmp->getHeight()-1); dbmpptr=-dbmpptr; } while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ // put_scanline_someplace(buffer[0], row_stride); if (cinfo.output_components==3) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255); } } else if (cinfo.output_components==1) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { int v=buffer[0][x]; bmpptr[x]=LICE_RGBA(v,v,v,255); } } else memset(bmpptr,0,4*cinfo.output_width); bmpptr+=dbmpptr; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); fclose(fp); return bmp; }
LICE_IBitmap *LICE_LoadPNGFromMemory(const void *data_in, int buflen, LICE_IBitmap *bmp) { if (buflen<8) return NULL; unsigned char *data = (unsigned char *)(void*)data_in; if(png_sig_cmp(data, 0, 8)) return NULL; pngReadStruct readStruct = {data, buflen}; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { return 0; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 0; } png_set_read_fn(png_ptr, &readStruct, staticPngReadFunc); png_read_info(png_ptr, info_ptr); unsigned int width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); //convert whatever it is to RGBA if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); color_type |= PNG_COLOR_MASK_ALPHA; } if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (color_type & PNG_COLOR_MASK_ALPHA) png_set_swap_alpha(png_ptr); else png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); LICE_IBitmap *delbmp = NULL; if (bmp) bmp->resize(width,height); else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height); if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height) { delete delbmp; png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return 0; } unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));; LICE_pixel *srcptr = bmp->getBits(); int dsrcptr=bmp->getRowSpan(); unsigned int i; for(i=0;i<height;i++) { row_pointers[i]=(unsigned char *)srcptr; srcptr+=dsrcptr; } png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); //put shit in correct order #if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3) for(i=0;i<height;i++) { unsigned char *bp = row_pointers[i]; int j=width; while (j-->0) { unsigned char a = bp[0]; unsigned char r = bp[1]; unsigned char g = bp[2]; unsigned char b = bp[3]; ((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a); bp+=4; } } #endif free(row_pointers); return bmp; }
TestMRPPWindow::TestMRPPWindow(HWND parent, std::string title) : MRPWindow(parent, title) { for (int i = 0; i < 8; ++i) { auto but = std::make_shared<WinButton>(this, std::to_string(i)); but->GenericNotifyCallback = [i](GenericNotifications) { readbg() << "you pressed " << i << "\n"; }; add_control(but); } // Button 0 toggless enabled state of button 1 m_controls[0]->GenericNotifyCallback = [this](GenericNotifications) { m_controls[1]->setEnabled(!m_controls[1]->isEnabled()); }; m_envcontrol1 = std::make_shared<EnvelopeControl>(this); // Button 3 toggless enabled state of envelope control m_controls[3]->GenericNotifyCallback = [this](GenericNotifications) { m_envcontrol1->setEnabled(!m_envcontrol1->isEnabled()); }; // Button 7 toggless visible state of button 0 m_controls[7]->GenericNotifyCallback = [this](GenericNotifications) { m_controls[0]->setVisible(!m_controls[0]->isVisible()); }; auto env = std::make_shared<breakpoint_envelope>("foo", LICE_RGBA(255, 255, 255, 255)); env->add_point({ 0.0, 0.5 , envbreakpoint::Power, 0.5 }, true); env->add_point({ 0.5, 0.0 , envbreakpoint::Power, 0.5 }, true); env->add_point({ 1.0, 0.5 }, true); m_envcontrol1->add_envelope(env); m_envcontrol1->GenericNotifyCallback = [this, env](GenericNotifications reason) { //if (reason == GenericNotifications::AfterManipulation) // generate_items_sequence(env, m_edit1->getText().c_str()); }; add_control(m_envcontrol1); // Button 5 does some Xenakios silliness m_controls[5]->GenericNotifyCallback = [this, env](GenericNotifications) { generate_items_sequence(env, m_edit1->getText().c_str()); }; m_label1 = std::make_shared<WinLabel>(this, "This is a label"); add_control(m_label1); m_edit1 = std::make_shared<WinLineEdit>(this, "C:/MusicAudio/pihla_ei/ei_mono_005.wav"); add_control(m_edit1); m_edit1->TextCallback = [this](std::string txt) { m_label1->setText(txt); }; // Button 6 launches bogus work in another thread to demo progress bar m_controls[6]->GenericNotifyCallback = [this](GenericNotifications) { m_progressbar1->setVisible(true); // we don't deal with multiple background tasks now, so disable the button to start the task m_controls[6]->setEnabled(false); static int rseed = 0; auto task = [this](int randseed) { std::mt19937 randgen(randseed); std::uniform_real_distribution<double> randdist(0.0, 1.0); double accum = 0.0; const int iterations = 50000000; double t0 = time_precise(); for (int i = 0; i < iterations; ++i) { accum += randdist(randgen); //accum += randdist(randgen); // Production code should not do this at this granularity, because setProgressValue deals with // an atomic value. but this is just a demo... m_progressbar1->setProgressValue(1.0 / iterations*i); } double t1 = time_precise(); auto finishtask = [=]() { m_edit1->setText(std::to_string(accum) + " elapsed time " + std::to_string(t1-t0)); m_progressbar1->setProgressValue(0.0); m_progressbar1->setVisible(false); m_controls[6]->setEnabled(true); }; execute_in_main_thread(finishtask); }; m_future1 = std::async(std::launch::async, task, rseed); ++rseed; }; // Button 1 shows popup menu m_controls[1]->GenericNotifyCallback = [this, env](GenericNotifications) { PopupMenu popmenu(getWindowHandle()); popmenu.add_menu_item("Menu entry 1", [](PopupMenu::CheckState) {}); popmenu.add_menu_item("Menu entry 2", m_menuitem2state, [this](PopupMenu::CheckState cs) { m_menuitem2state = cs; }); popmenu.add_menu_item("Menu entry 3", m_menuitem3state, [this](PopupMenu::CheckState cs) { m_menuitem3state = cs; }); PopupMenu submenu(getWindowHandle()); submenu.add_menu_item("Submenu entry 1", [](PopupMenu::CheckState) { readbg() << "submenu entry 1\n"; }); submenu.add_menu_item("Submenu entry 2", [](PopupMenu::CheckState) { readbg() << "submenu entry 2\n"; }); PopupMenu subsubmenu(getWindowHandle()); for (int i = 0; i < 8; ++i) { subsubmenu.add_menu_item(std::string("Subsubmenu entry ") + std::to_string(i + 1), [i](PopupMenu::CheckState) { readbg() << "subsubmenu entry " << i + 1 << "\n"; }); } submenu.add_submenu("Going still deeper", subsubmenu); popmenu.add_submenu("More stuff", submenu); popmenu.execute(m_controls[1]->getXPosition(), m_controls[1]->getYPosition()); }; // Button 4 removes envelope points with value over 0.5 m_controls[4]->GenericNotifyCallback = [this, env](GenericNotifications) { env->remove_points_conditionally([](const envbreakpoint& pt) { return pt.get_y() > 0.5; }); m_envcontrol1->repaint(); }; m_combo1 = std::make_shared<WinComboBox>(this); m_combo1->addItem("Apple", -9001); m_combo1->addItem("Pear", 666); m_combo1->addItem("Kiwi", 42); m_combo1->addItem("Banana", 100); m_combo1->SelectedChangedCallback = [this](int index) { int user_id = m_combo1->userIDfromIndex(index); readbg() << "combo index " << index << " userid " << user_id << "\n"; }; add_control(m_combo1); m_combo1->setSelectedUserID(42); m_combo2 = std::make_shared<WinComboBox>(this); m_combo2->addItem("Item 1", 100); m_combo2->addItem("Item 2", 101); m_combo2->addItem("Item 3", 102); m_combo2->addItem("Item 4", 103); m_combo2->SelectedChangedCallback = [this](int index) { int user_id = m_combo2->userIDfromIndex(index); readbg() << "combo index " << index << " userid " << user_id << "\n"; }; add_control(m_combo2); m_combo2->setSelectedIndex(0); m_slider1 = std::make_shared<ReaSlider>(this, 0.5); //m_slider1->setValueConverter(std::make_shared<FFTSizesValueConverter>()); m_slider1->SliderValueCallback = [this](GenericNotifications, double x) { m_label1->setText(std::to_string(x)); m_progressbar1->setProgressValue(x); }; add_control(m_slider1); m_zoomscroll1 = std::make_shared<ZoomScrollBar>(this); add_control(m_zoomscroll1); m_zoomscroll1->RangeChangedCallback = [this](double t0, double t1) { m_envcontrol1->setViewTimeRange(t0, t1); }; m_progressbar1 = std::make_shared<ProgressControl>(this); m_progressbar1->setVisible(false); }
LICE_IBitmap *LICE_LoadGIF(const char *filename, LICE_IBitmap *bmp, int *nframes) { GifFileType *fp=DGifOpenFileName(filename); if (!fp) return 0; GifRecordType RecordType; GifByteType *Extension; int ExtCode; do { if (DGifGetRecordType(fp, &RecordType) == GIF_ERROR) { DGifCloseFile(fp); return 0; } switch (RecordType) { case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(fp) == GIF_ERROR) { DGifCloseFile(fp); return 0; } // todo: support transparency // todo: have it buffer all frames and output frame count if (nframes) *nframes=1; // placeholder { int width=fp->Image.Width,height=fp->Image.Height; if (bmp) { bmp->resize(width,height); if (bmp->getWidth() != (int)width || bmp->getHeight() != (int)height) { DGifCloseFile(fp); return 0; } } else bmp=new LICE_MemBitmap(width,height); LICE_pixel *bmpptr = bmp->getBits(); int dbmpptr=bmp->getRowSpan(); if (bmp->isFlipped()) { bmpptr += dbmpptr*(bmp->getHeight()-1); dbmpptr=-dbmpptr; } GifPixelType *linebuf=(GifPixelType*)malloc(width*sizeof(GifPixelType)); int y; int cmap[256]; for (y=0;y<256;y++) { if (fp->SColorMap&&y<fp->SColorMap->ColorCount&&fp->SColorMap->Colors) { GifColorType *ct=fp->SColorMap->Colors+y; cmap[y]=LICE_RGBA(ct->Red,ct->Green,ct->Blue,255); } else cmap[y]=0; } for (y=0; y < height; y ++) { if (DGifGetLine(fp,linebuf,width)==GIF_ERROR) break; int x; for (x = 0; x < width; x ++) { bmpptr[x]=cmap[linebuf[x]&0xff]; } bmpptr += dbmpptr; } free(linebuf); DGifCloseFile(fp); return bmp; } break; case EXTENSION_RECORD_TYPE: if (DGifGetExtension(fp, &ExtCode, &Extension) == GIF_ERROR) { DGifCloseFile(fp); return 0; } while (Extension != NULL) { if (DGifGetExtensionNext(fp, &Extension) == GIF_ERROR) { DGifCloseFile(fp); return 0; } } break; case TERMINATE_RECORD_TYPE: break; default: /* Should be traps by DGifGetRecordType. */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); DGifCloseFile(fp); return 0; }
void LICE_TexGen_Marble(LICE_IBitmap *dest, RECT *rect, float rv, float gv, float bv, float intensity) { int span=dest->getRowSpan(); int w = dest->getWidth(); int h = dest->getHeight(); int x = 0; int y = 0; if(rect) { x = rect->left; y = rect->top; w = rect->right - rect->left; h = rect->bottom - rect->top; } if (x<0) { w+=x; x=0; } if (y<0) { h+=y; y=0; } if (x+w > dest->getWidth()) w=dest->getWidth()-x; if (y+h > dest->getHeight()) h=dest->getHeight()-y; if (w<1 || h<1) return; LICE_pixel *startp = dest->getBits(); if (dest->isFlipped()) { startp += x + (dest->getHeight()-1-y)*span; span=-span; } else startp += x + y*span; //simple 16bit marble noise generator #define ROL(x,y) ((x<<(y))|(((unsigned short)x)>>(16-(y)))) #define ROR(x,y) ((((unsigned short)x)>>(y))|(x<<(16-(y)))) intensity/=1024.0f; int maxc = 0; { LICE_pixel *p = startp; short n1 = 0, n2 = 0; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { n1 += n2; n1 = ROL(n1, n2&0xf); n2 += 2; n2 = ROR(n2, 1); int val = (int)(n1*intensity)+1; LICE_pixel c = w; LICE_pixel c2 = w/2; if(i>0) { c = p[j-span]; if(j==0) c2 = p[(w-1)-span]; else c2 = p[(j-1)-span]; } int pix = (((c + c2)/2) + val); if(pix>maxc) maxc = pix; p[j] = pix; } p+=span; } } //normalize values and apply gamma { LICE_pixel *p = startp; float sc=255.0f/maxc; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { float col = (float)fabs(p[j]*sc); p[j] = LICE_RGBA((int)(col*rv),(int)(col*gv),(int)(col*bv),255); } p+=span; } } }
void LICE_TexGen_Noise(LICE_IBitmap *dest, RECT *rect, float rv, float gv, float bv, float intensity, int mode, int smooth) { initNoise(); int span=dest->getRowSpan(); int w = dest->getWidth(); int h = dest->getHeight(); int x = 0; int y = 0; if(rect) { x = rect->left; y = rect->top; w = rect->right - rect->left; h = rect->bottom - rect->top; } if (x<0) { w+=x; x=0; } if (y<0) { h+=y; y=0; } if (x+w > dest->getWidth()) w=dest->getWidth()-x; if (y+h > dest->getHeight()) h=dest->getHeight()-y; if (w<1 || h<1) return; LICE_pixel *startp = dest->getBits(); if (dest->isFlipped()) { startp += x + (dest->getHeight()-1-y)*span; span=-span; } else startp += x + y*span; { LICE_pixel *p = startp; for(int i=0;i<h;i++) { for(int j=0;j<w;j++) { float x = (float)j/w*16*intensity; float y = (float)i/h*16*intensity; float val = 0; int size = smooth; while(size>=1) { switch(mode) { case NOISE_MODE_NORMAL: val += noise(x/size, y/size)*size; break; case NOISE_MODE_WOOD: val += (float)cos( x/size + noise(x/size,y/size) )*size/2; break; } size /= 2; } float col = (float)fabs(val/smooth)*255; if(col>255) col=255; p[j] = LICE_RGBA((int)(col*rv),(int)(col*gv),(int)(col*bv),255); } p+=span; } } }
LICE_IBitmap *LICE_LoadPNG(const char *filename, LICE_IBitmap *bmp) { FILE *fp = NULL; #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8) #ifdef WDL_SUPPORT_WIN9X if (GetVersion()<0x80000000) #endif { WCHAR wf[2048]; if (MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,filename,-1,wf,2048)) fp = _wfopen(wf,L"rb"); } #endif if (!fp) fp = fopen(filename,"rb"); if (!fp) return 0; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { fclose(fp); return 0; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); return 0; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); unsigned int width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); //convert whatever it is to RGBA if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); color_type |= PNG_COLOR_MASK_ALPHA; } if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (color_type & PNG_COLOR_MASK_ALPHA) png_set_swap_alpha(png_ptr); else png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); LICE_IBitmap *delbmp = NULL; if (bmp) bmp->resize(width,height); else delbmp = bmp = new WDL_NEW LICE_MemBitmap(width,height); if (!bmp || bmp->getWidth() != (int)width || bmp->getHeight() != (int)height) { delete delbmp; png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); return 0; } unsigned char **row_pointers=(unsigned char **)malloc(height*sizeof(unsigned char *));; LICE_pixel *srcptr = bmp->getBits(); int dsrcptr=bmp->getRowSpan(); if (bmp->isFlipped()) { srcptr += dsrcptr*(bmp->getHeight()-1); dsrcptr=-dsrcptr; } unsigned int i; for(i=0;i<height;i++) { row_pointers[i]=(unsigned char *)srcptr; srcptr+=dsrcptr; } png_read_image(png_ptr, row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); #if !(LICE_PIXEL_A == 0 && LICE_PIXEL_R == 1 && LICE_PIXEL_G == 2 && LICE_PIXEL_B == 3) for(i=0;i<height;i++) { unsigned char *bp = row_pointers[i]; int j=width; while (j-->0) { unsigned char a = bp[0]; unsigned char r = bp[1]; unsigned char g = bp[2]; unsigned char b = bp[3]; ((LICE_pixel*)bp)[0] = LICE_RGBA(r,g,b,a); bp+=4; } } #endif free(row_pointers); return bmp; }
LICE_IBitmap *LICE_LoadJPGFromResource(HINSTANCE hInst, int resid, LICE_IBitmap *bmp) { #ifdef _WIN32 HRSRC hResource = FindResource(hInst, MAKEINTRESOURCE(resid), "JPG"); if(!hResource) return NULL; DWORD imageSize = SizeofResource(hInst, hResource); if(imageSize < 8) return NULL; HGLOBAL res = LoadResource(hInst, hResource); const void* pResourceData = LockResource(res); if(!pResourceData) return NULL; unsigned char *data = (unsigned char *)pResourceData; struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr={0,}; JSAMPARRAY buffer; int row_stride; jerr.pub.error_exit = LICEJPEG_Error; jerr.pub.emit_message = LICEJPEG_EmitMsg; jerr.pub.output_message = LICEJPEG_OutMsg; jerr.pub.format_message = LICEJPEG_FmtMsg; jerr.pub.reset_error_mgr = LICEJPEG_reset_error_mgr; cinfo.err = &jerr.pub; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); DeleteObject(res); return 0; } jpeg_create_decompress(&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (struct jpeg_source_mgr)); cinfo.src->init_source = LICEJPEG_init_source; cinfo.src->fill_input_buffer = LICEJPEG_fill_input_buffer; cinfo.src->skip_input_data = LICEJPEG_skip_input_data; cinfo.src->resync_to_restart = jpeg_resync_to_restart; cinfo.src->term_source = LICEJPEG_term_source; cinfo.src->next_input_byte = data; cinfo.src->bytes_in_buffer = imageSize; jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); if (bmp) { bmp->resize(cinfo.output_width,cinfo.output_height); if (bmp->getWidth() != (int)cinfo.output_width || bmp->getHeight() != (int)cinfo.output_height) { jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); DeleteObject(res); return 0; } } else bmp=new LICE_MemBitmap(cinfo.output_width,cinfo.output_height); LICE_pixel *bmpptr = bmp->getBits(); int dbmpptr=bmp->getRowSpan(); if (bmp->isFlipped()) { bmpptr += dbmpptr*(bmp->getHeight()-1); dbmpptr=-dbmpptr; } while (cinfo.output_scanline < cinfo.output_height) { /* jpeg_read_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could ask for * more than one scanline at a time if that's more convenient. */ jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ // put_scanline_someplace(buffer[0], row_stride); if (cinfo.output_components==3) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { bmpptr[x]=LICE_RGBA(buffer[0][x*3],buffer[0][x*3+1],buffer[0][x*3+2],255); } } else if (cinfo.output_components==1) { int x; for (x = 0; x < (int)cinfo.output_width; x++) { int v=buffer[0][x]; bmpptr[x]=LICE_RGBA(v,v,v,255); } } else { memset(bmpptr,0,4*cinfo.output_width); } bmpptr+=dbmpptr; } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); // we created cinfo.src with some special alloc so I think it gets collected DeleteObject(res); return bmp; #else return 0; #endif }
inline LICE_pixel LiceColor(const IColor* pColor) { return LICE_RGBA(pColor->R, pColor->G, pColor->B, pColor->A); }
static LICE_IBitmap *icoToBitmap(HICON icon, LICE_IBitmap *bmpOut) { int icon_w = 16, icon_h=16; #ifdef _WIN32 ICONINFO ii={0,}; if (GetIconInfo(icon,&ii)) { bool blah=false; if (ii.hbmColor) { BITMAP bm={0,}; if (GetObject(ii.hbmColor,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight) { icon_w=bm.bmWidth; icon_h=bm.bmHeight; blah=true; } DeleteObject(ii.hbmColor); } if (ii.hbmMask) { BITMAP bm={0,}; if (!blah && GetObject(ii.hbmMask,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight) { icon_w=bm.bmWidth; icon_h=bm.bmHeight; } DeleteObject(ii.hbmMask); } } #else BITMAP bm={0,}; if (GetObject(icon,sizeof(bm),&bm) && bm.bmWidth && bm.bmHeight) // SWELL's GetObject() works on icons { icon_w=bm.bmWidth; icon_h=bm.bmHeight; } #endif LICE_SysBitmap tempbm(icon_w*2,icon_h); LICE_FillRect(&tempbm,0,0,icon_w,icon_h,LICE_RGBA(0,0,0,255),1.0f,LICE_BLIT_MODE_COPY); #ifdef _WIN32 DrawIconEx(tempbm.getDC(),0,0,icon,icon_w,icon_h,0,NULL,DI_NORMAL); #else { RECT r={0,0,icon_w,icon_h}; DrawImageInRect(tempbm.getDC(),icon,&r); } #endif LICE_FillRect(&tempbm,icon_w,0,icon_w,icon_h,LICE_RGBA(255,255,255,255),1.0f,LICE_BLIT_MODE_COPY); #ifdef _WIN32 DrawIconEx(tempbm.getDC(),icon_w,0,icon,icon_w,icon_h,0,NULL,DI_NORMAL); #else { RECT r={icon_w,0,icon_w+icon_w,icon_h}; DrawImageInRect(tempbm.getDC(),icon,&r); } #endif if (!bmpOut) bmpOut = new LICE_MemBitmap(icon_w,icon_h); else bmpOut->resize(icon_w,icon_h); int y; // since we have the image drawn on white and on black, we can calculate the alpha channel... for(y=0;y<icon_h;y++) { int x; for(x=0;x<icon_w;x++) { LICE_pixel p = LICE_GetPixel(&tempbm,x,y); LICE_pixel p2 = LICE_GetPixel(&tempbm,x+icon_w,y); int r1=LICE_GETR(p); int g1=LICE_GETG(p); int b1=LICE_GETB(p); int alpha=255 - (LICE_GETR(p2)-r1); if (alpha>=255) alpha=255; else if (alpha>0) { r1 = (r1*255)/alpha; // LICE stores its alpha channel non-premultiplied, so we need to scale these up. g1 = (g1*255)/alpha; b1 = (b1*255)/alpha; if (r1>255)r1=255; if (g1>255)g1=255; if (b1>255)b1=255; } else alpha=0; LICE_PutPixel(bmpOut,x,y,LICE_RGBA(r1,g1,b1,alpha),1.0f,LICE_BLIT_MODE_COPY); } } return bmpOut; }
void WDL_VirtualIconButton::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect) { int col; float alpha = (m_grayed ? 0.25f : 1.0f) * m_alpha; bool isdown = !!(m_pressed&1); bool ishover = !!(m_pressed&2); if (m_iconCfg && m_iconCfg->image && !m_iconCfg->image_issingle) { bool swapupdown = (m_checkstate > 0); bool isdownimg = (swapupdown != isdown); RECT r=m_position; int sx=0; int sy=0; int w=m_iconCfg->image->getWidth(); int h=m_iconCfg->image->getHeight(); if (w>0 && (m_iconCfg->image_ltrb_used.flags&2)) w-=2; w/=3; if (w>0 && h > 0) { if (m_is_button) { if (isdownimg) sx += w*2; else if (ishover) sx += w; } if (m_iconCfg->image_ltrb_used.flags&2) { WDL_VirtualWnd_BGCfg cfg={0,}; LICE_SubBitmap sb(m_iconCfg->image,sx+1,sy+1,w,h-2); cfg.bgimage = &sb; cfg.bgimage_lt[0] = m_iconCfg->image_ltrb_main[0]+1; // image_ltrb_main expects 1-based number cfg.bgimage_lt[1] = m_iconCfg->image_ltrb_main[1]+1; cfg.bgimage_rb[0] = m_iconCfg->image_ltrb_main[2]+1; cfg.bgimage_rb[1] = m_iconCfg->image_ltrb_main[3]+1; cfg.bgimage_noalphaflags=0; WDL_VirtualWnd_ScaledBlitBG(drawbm,&cfg, r.left+origin_x,r.top+origin_y,r.right-r.left,r.bottom-r.top, r.left+origin_x,r.top+origin_y,r.right-r.left,r.bottom-r.top, alpha,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR|LICE_BLIT_USE_ALPHA); } else LICE_ScaledBlit(drawbm,m_iconCfg->image,r.left+origin_x,r.top+origin_y, r.right-r.left, r.bottom-r.top, (float)sx,(float)sy,(float)w,(float)h, alpha, LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR|LICE_BLIT_USE_ALPHA); } } else { RECT r=m_position; r.left+=origin_x; r.right+=origin_x; r.top+=origin_y; r.bottom+=origin_y; if (m_is_button) { if (WDL_STYLE_WantGlobalButtonBackground(&col)) { LICE_FillRect(drawbm,r.left,r.top,r.right-r.left,r.bottom-r.top,LICE_RGBA_FROMNATIVE(col,255),alpha,LICE_BLIT_MODE_COPY); } if (ishover || m_forceborder || WDL_STYLE_WantGlobalButtonBorders()) { int cidx=isdown?COLOR_3DSHADOW:COLOR_3DHILIGHT; int pencol = GSC(cidx); pencol = LICE_RGBA_FROMNATIVE(pencol,255); LICE_Line(drawbm,r.left,r.bottom-1,r.left,r.top,pencol,alpha,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.left,r.top,r.right-1,r.top,pencol,alpha,LICE_BLIT_MODE_COPY,false); cidx = isdown?COLOR_3DHILIGHT:COLOR_3DSHADOW; pencol = GSC(cidx); pencol = LICE_RGBA_FROMNATIVE(pencol,255); LICE_Line(drawbm,r.right-1,r.top,r.right-1,r.bottom-1,pencol,alpha,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,r.right-1,r.bottom-1,r.left,r.bottom-1,pencol,alpha,LICE_BLIT_MODE_COPY,false); } } if (m_iconCfg && m_iconCfg->image) { int sz=16,sz2=16; WDL_STYLE_ScaleImageCoords(&sz,&sz2); //if (m_position.right-m_position.left > 24) sz=m_position.right-m_position.left-8; int x=r.left+((r.right-r.left)-sz)/2; int y=r.top+((r.bottom-r.top)-sz2)/2; if (m_is_button) { if (isdown && ishover) { x++; y++; } } LICE_ScaledBlit(drawbm,m_iconCfg->image,x,y,sz,sz2,0.0f,0.0f, (float)m_iconCfg->image->getWidth(), (float)m_iconCfg->image->getHeight(),alpha,LICE_BLIT_MODE_COPY|LICE_BLIT_FILTER_BILINEAR|LICE_BLIT_USE_ALPHA); } } if (!m_iconCfg || m_forcetext) { RECT r2=m_position; r2.left+=origin_x; r2.right+=origin_x; r2.top+=origin_y; r2.bottom+=origin_y; if (m_checkstate>=0 && !m_iconCfg) { RECT tr=r2; int sz=tr.bottom-tr.top; r2.left+=sz+2; tr.top+=2; tr.bottom-=2; sz-=4; sz&=~1; LICE_FillRect(drawbm ,tr.left,tr.top,sz,sz,LICE_RGBA(255,255,255,255),alpha,LICE_BLIT_MODE_COPY); LICE_Line(drawbm,tr.left,tr.top,tr.left+sz,tr.top,LICE_RGBA(128,128,128,255),alpha,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,tr.left+sz,tr.top,tr.left+sz,tr.bottom,LICE_RGBA(128,128,128,255),alpha,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,tr.left+sz,tr.bottom,tr.left,tr.bottom,LICE_RGBA(128,128,128,255),alpha,LICE_BLIT_MODE_COPY,false); LICE_Line(drawbm,tr.left,tr.bottom,tr.left,tr.top,LICE_RGBA(128,128,128,255),alpha,LICE_BLIT_MODE_COPY,false); int nl = (m_checkstate>0) ? 3:0; if (isdown) nl ^= 2; if (nl&1) LICE_Line(drawbm,tr.left+2,tr.bottom-2,tr.left+sz-2,tr.top+2,LICE_RGBA(0,0,0,255),alpha,LICE_BLIT_MODE_COPY,false); if (nl&2) LICE_Line(drawbm,tr.left+2,tr.top+2,tr.left+sz-2,tr.bottom-2,LICE_RGBA(0,0,0,255),alpha,LICE_BLIT_MODE_COPY,false); } LICE_IFont *font = m_textfont; bool isVert=false; if (font && m_textfontv && m_position.right-m_position.left < m_position.bottom - m_position.top) { isVert=true; font = m_textfontv; } // draw text if (font&&m_textlbl.Get()[0]) { int fgc=m_forcetext_color ? m_forcetext_color : LICE_RGBA_FROMNATIVE(GSC(COLOR_BTNTEXT),255); //font->SetCombineMode(LICE_BLIT_MODE_COPY, alpha); // this affects the glyphs that get cached font->SetBkMode(TRANSPARENT); font->SetTextColor(fgc); r2.left += m_margin_l; r2.right -= m_margin_r; r2.top += m_margin_t; r2.bottom -= m_margin_b; if (isdown) { if (m_textalign<0) r2.left+=1; else if (m_textalign>0) r2.right+=1; else r2.left+=2; r2.top+=2; } int f = DT_SINGLELINE|DT_NOPREFIX; if (isVert) { if (m_textalign == 0) { RECT mr={0,}; font->DrawText(drawbm,m_textlbl.Get(),-1,&mr,f|DT_CALCRECT); f |= (mr.bottom < r2.bottom-r2.top) ? DT_VCENTER : DT_TOP; } else f |= m_textalign<0?DT_TOP:DT_BOTTOM; f |= DT_CENTER; } else { if (m_textalign == 0) { RECT mr={0,}; font->DrawText(drawbm,m_textlbl.Get(),-1,&mr,f|DT_CALCRECT); f |= (mr.right < r2.right-r2.left) ? DT_CENTER : DT_LEFT; } else f |= m_textalign<0?DT_LEFT:DT_RIGHT; f |= DT_VCENTER; } font->DrawText(drawbm,m_textlbl.Get(),-1,&r2,f); } } if (m_bgcol1_msg) { int brcol=-100; SendCommand(m_bgcol1_msg,(INT_PTR)&brcol,GetID(),this); if (brcol != -100) { RECT r=m_position; int bh=(r.bottom-r.top)/5; if (bh<1) bh=1; int bw=(r.right-r.left)/5; if (bw<1) bw=1; LICE_FillRect(drawbm, r.left+origin_x,r.top+origin_y, r.right-r.left, bh,LICE_RGBA_FROMNATIVE(brcol,255),0.75,LICE_BLIT_MODE_COPY); LICE_FillRect(drawbm, r.left+origin_x,r.top+origin_y+bh, bw, r.bottom-r.top-bh*2,LICE_RGBA_FROMNATIVE(brcol,255),0.75,LICE_BLIT_MODE_COPY); LICE_FillRect(drawbm, r.right+origin_x-bw,r.top+origin_y+bh, bw, r.bottom-r.top-bh*2,LICE_RGBA_FROMNATIVE(brcol,255),0.75,LICE_BLIT_MODE_COPY); LICE_FillRect(drawbm, r.left+origin_x,r.bottom+origin_y-bh, r.right-r.left, bh,LICE_RGBA_FROMNATIVE(brcol,255),0.75,LICE_BLIT_MODE_COPY); } } }
LICE_IBitmap *LICE_LoadPCX(const char *filename, LICE_IBitmap *_bmp) { FILE *fp = fopen(filename,"rb"); if(!fp) return 0; fgetc(fp); if (fgetc(fp) != 5) { fclose(fp); return NULL; } if (fgetc(fp) != 1) { fclose(fp); return NULL; } if (fgetc(fp) != 8) { fclose(fp); return NULL; } int sx = fgetc(fp); sx += fgetc(fp)<<8; int sy = fgetc(fp); sy += fgetc(fp)<<8; int ex = fgetc(fp); ex += fgetc(fp)<<8; int ey = fgetc(fp); ey += fgetc(fp)<<8; unsigned char pal[768]; fseek(fp,-769,SEEK_END); if (fgetc(fp) != 12) { fclose(fp); return NULL; } fread(pal,1,768,fp); if (feof(fp)) { fclose(fp); return NULL; } LICE_IBitmap *usebmp = NULL; if (_bmp) (usebmp=_bmp)->resize(ex-sx+1,ey-sy+1); else usebmp = new LICE_MemBitmap(ex-sx+1,ey-sy+1); fseek(fp,128,SEEK_SET); LICE_Clear(usebmp,0); int y = usebmp->getHeight(); int w = usebmp->getWidth(); int rowspan = usebmp->getRowSpan(); LICE_pixel *pout = usebmp->getBits(); if (usebmp->isFlipped()) { pout += rowspan*(y-1); rowspan=-rowspan; } while (y--) { int xpos = 0; while (xpos < w) { int c = fgetc(fp); if (c&~255) break; if ((c & 192) == 192) { int oc = (fgetc(fp))&255; LICE_pixel t=LICE_RGBA(pal[oc*3],pal[oc*3+1],pal[oc*3+2],255); c&=63; while (c-- && xpos<w) pout[xpos++] = t; } else pout[xpos++] = LICE_RGBA(pal[c*3],pal[c*3+1],pal[c*3+2],255); } pout+=rowspan; } return usebmp; }
static LICE_IBitmap *hbmToBit(HBITMAP hbm, LICE_IBitmap *bmp) { BITMAP bm; GetObject(hbm, sizeof(BITMAP), (LPSTR)&bm); LICE_SysBitmap sysbitmap(bm.bmWidth,bm.bmHeight); #ifdef _WIN32 HDC hdc=CreateCompatibleDC(NULL); HGDIOBJ oldBM=SelectObject(hdc,hbm); BitBlt(sysbitmap.getDC(),0,0,bm.bmWidth,bm.bmHeight,hdc,0,0,SRCCOPY); GdiFlush(); if (!bmp) bmp=new LICE_MemBitmap(bm.bmWidth,bm.bmHeight); LICE_Copy(bmp,&sysbitmap); SelectObject(hdc,oldBM); DeleteDC(hdc); #else LICE_Clear(&sysbitmap,0); RECT r={0,0,bm.bmWidth,bm.bmHeight}; DrawImageInRect(sysbitmap.getDC(),hbm,&r); if (!bmp) bmp=new LICE_MemBitmap(bm.bmWidth,bm.bmHeight); LICE_Copy(bmp,&sysbitmap); #endif LICE_FillRect(bmp,0,0,bmp->getWidth(),bmp->getHeight(),LICE_RGBA(0,0,0,255),1.0f,LICE_BLIT_MODE_ADD); return bmp; }