void NinePieceImageGrid::setDrawInfoEdge(NinePieceDrawInfo& drawInfo, NinePiece piece) const { IntSize edgeSourceSize = m_imageSize - IntSize(m_left.slice + m_right.slice, m_top.slice + m_bottom.slice); IntSize edgeDestinationSize = m_borderImageArea.size() - IntSize(m_left.width + m_right.width, m_top.width + m_bottom.width); switch (piece) { case LeftPiece: setVerticalEdge(drawInfo, m_left, subrect(m_imageSize, 0, m_top.slice, m_left.slice, edgeSourceSize.height()), subrect(m_borderImageArea, 0, m_top.width, m_left.width, edgeDestinationSize.height()), m_verticalTileRule); break; case RightPiece: setVerticalEdge(drawInfo, m_right, subrect(m_imageSize, -m_right.slice, m_top.slice, m_right.slice, edgeSourceSize.height()), subrect(m_borderImageArea, -m_right.width, m_top.width, m_right.width, edgeDestinationSize.height()), m_verticalTileRule); break; case TopPiece: setHorizontalEdge(drawInfo, m_top, subrect(m_imageSize, m_left.slice, 0, edgeSourceSize.width(), m_top.slice), subrect(m_borderImageArea, m_left.width, 0, edgeDestinationSize.width(), m_top.width), m_horizontalTileRule); break; case BottomPiece: setHorizontalEdge(drawInfo, m_bottom, subrect(m_imageSize, m_left.slice, -m_bottom.slice, edgeSourceSize.width(), m_bottom.slice), subrect(m_borderImageArea, m_left.width, -m_bottom.width, edgeDestinationSize.width(), m_bottom.width), m_horizontalTileRule); break; default: ASSERT_NOT_REACHED(); break; } }
void NinePieceImageGrid::setDrawInfoCorner(NinePieceDrawInfo& drawInfo, NinePiece piece) const { switch (piece) { case TopLeftPiece: setCornerPiece(drawInfo, m_top.isDrawable() && m_left.isDrawable(), subrect(m_imageSize, 0, 0, m_left.slice, m_top.slice), subrect(m_borderImageArea, 0, 0, m_left.width, m_top.width)); break; case BottomLeftPiece: setCornerPiece(drawInfo, m_bottom.isDrawable() && m_left.isDrawable(), subrect(m_imageSize, 0, -m_bottom.slice, m_left.slice, m_bottom.slice), subrect(m_borderImageArea, 0, -m_bottom.width, m_left.width, m_bottom.width)); break; case TopRightPiece: setCornerPiece(drawInfo, m_top.isDrawable() && m_right.isDrawable(), subrect(m_imageSize, -m_right.slice, 0, m_right.slice, m_top.slice), subrect(m_borderImageArea, -m_right.width, 0, m_right.width, m_top.width)); break; case BottomRightPiece: setCornerPiece(drawInfo, m_bottom.isDrawable() && m_right.isDrawable(), subrect(m_imageSize, -m_right.slice, -m_bottom.slice, m_right.slice, m_bottom.slice), subrect(m_borderImageArea, -m_right.width, -m_bottom.width, m_right.width, m_bottom.width)); break; default: ASSERT_NOT_REACHED(); break; } }
bool wxGCDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC *source, wxCoord xsrc, wxCoord ysrc, int logical_func , bool WXUNUSED(useMask), wxCoord xsrcMask, wxCoord ysrcMask ) { wxCHECK_MSG( Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid DC") ); wxCHECK_MSG( source->Ok(), false, wxT("wxGCDC(cg)::DoBlit - invalid source DC") ); if ( logical_func == wxNO_OP ) return true; else if ( !m_graphicContext->SetLogicalFunction( logical_func ) ) { wxFAIL_MSG( wxT("Logical function is not supported by the graphics context.") ); return false; } if (xsrcMask == -1 && ysrcMask == -1) { xsrcMask = xsrc; ysrcMask = ysrc; } wxRect subrect(source->LogicalToDeviceX(xsrc), source->LogicalToDeviceY(ysrc), source->LogicalToDeviceXRel(width), source->LogicalToDeviceYRel(height)); // if needed clip the subrect down to the size of the source DC wxCoord sw, sh; source->GetSize(&sw, &sh); sw = source->LogicalToDeviceXRel(sw); sh = source->LogicalToDeviceYRel(sh); if (subrect.x + subrect.width > sw) subrect.width = sw - subrect.x; if (subrect.y + subrect.height > sh) subrect.height = sh - subrect.y; wxBitmap blit = source->GetAsBitmap( &subrect ); if ( blit.Ok() ) { m_graphicContext->DrawBitmap( blit, xdest, ydest, wxMin(width, blit.GetWidth()), wxMin(height, blit.GetHeight())); } else { wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") ); return false; } // reset logical function m_graphicContext->SetLogicalFunction( m_logicalFunction ); return true; }
void NinePieceImageGrid::setDrawInfoMiddle(NinePieceDrawInfo& drawInfo) const { IntSize sourceSize = m_imageSize - IntSize(m_left.slice + m_right.slice, m_top.slice + m_bottom.slice); IntSize destinationSize = m_borderImageArea.size() - IntSize(m_left.width + m_right.width, m_top.width + m_bottom.width); drawInfo.isDrawable = m_fill && !sourceSize.isEmpty() && !destinationSize.isEmpty(); if (!drawInfo.isDrawable) return; drawInfo.source = subrect(m_imageSize, m_left.slice, m_top.slice, sourceSize.width(), sourceSize.height()); drawInfo.destination = subrect(m_borderImageArea, m_left.width, m_top.width, destinationSize.width(), destinationSize.height()); FloatSize middleScaleFactor(1, 1); if (m_top.isDrawable()) middleScaleFactor.setWidth(m_top.scale()); else if (m_bottom.isDrawable()) middleScaleFactor.setWidth(m_bottom.scale()); if (m_left.isDrawable()) middleScaleFactor.setHeight(m_left.scale()); else if (m_right.isDrawable()) middleScaleFactor.setHeight(m_right.scale()); if (!sourceSize.isEmpty()) { // For "stretch" rules, just override the scale factor and replace. We only have to do this for the center tile, // since sides don't even use the scale factor unless they have a rule other than "stretch". The middle however // can have "stretch" specified in one axis but not the other, so we have to correct the scale here. if (m_horizontalTileRule == (Image::TileRule)StretchImageRule) middleScaleFactor.setWidth((float) destinationSize.width() / sourceSize.width()); if (m_verticalTileRule == (Image::TileRule)StretchImageRule) middleScaleFactor.setHeight((float) destinationSize.height() / sourceSize.height()); } drawInfo.tileScale = middleScaleFactor; drawInfo.tileRule = { m_horizontalTileRule, m_verticalTileRule }; }
void Level::render(sf::RenderWindow& window) { sf::Sprite tile; tile.setTexture(*m_tileset); int startX = ( window.getView().getCenter().x - (window.getView().getSize().x / 2) ) / 32; int startY = ( window.getView().getCenter().y - (window.getView().getSize().y / 2) ) / 32; int endX = startX + ( window.getView().getSize().x/32 ) + 2; int endY = startY + ( window.getView().getSize().y/32 ) + 2; if( startX < 0 ) startX = 0; if( startY < 0 ) startY = 0; if( startX > static_cast<int>(m_width) ) startX = m_width; if( startY > static_cast<int>(m_height) ) startY = m_height; if( endX < 0 ) endX = 0; if( endY < 0 ) endY = 0; if( endX > static_cast<int>(m_width) ) endX = m_width; if( endY > static_cast<int>(m_height) ) endY = m_height; for( int y = startY; y < endY; y++ ) { for( int x = startX; x < endX; x++ ) { if(!m_fogmap[x][y] && tiles[x][y] != 0) { int id = tiles[x][y]; sf::IntRect subrect( id * 32, 0, 32, 32 ); tile.setTextureRect(subrect); tile.setPosition(x * 32, y * 32); window.draw(tile); } } } }
bool wxGCDCImpl::DoStretchBlit( wxCoord xdest, wxCoord ydest, wxCoord dstWidth, wxCoord dstHeight, wxDC *source, wxCoord xsrc, wxCoord ysrc, wxCoord srcWidth, wxCoord srcHeight, wxRasterOperationMode logical_func , bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid DC") ); wxCHECK_MSG( source->IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid source DC") ); if ( logical_func == wxNO_OP ) return true; wxCompositionMode mode = TranslateRasterOp(logical_func); if ( mode == wxCOMPOSITION_INVALID ) { wxFAIL_MSG( wxT("Blitting is not supported with this logical operation.") ); return false; } wxRect subrect(source->LogicalToDeviceX(xsrc), source->LogicalToDeviceY(ysrc), source->LogicalToDeviceXRel(srcWidth), source->LogicalToDeviceYRel(srcHeight)); const wxRect subrectOrig = subrect; // clip the subrect down to the size of the source DC wxRect clip; source->GetSize(&clip.width, &clip.height); subrect.Intersect(clip); if (subrect.width == 0) return true; bool retval = true; wxCompositionMode formerMode = m_graphicContext->GetCompositionMode(); if (m_graphicContext->SetCompositionMode(mode)) { wxAntialiasMode formerAa = m_graphicContext->GetAntialiasMode(); if (mode == wxCOMPOSITION_XOR) { m_graphicContext->SetAntialiasMode(wxANTIALIAS_NONE); } if (xsrcMask == -1 && ysrcMask == -1) { xsrcMask = xsrc; ysrcMask = ysrc; } wxBitmap blit = source->GetAsBitmap( &subrect ); if ( blit.IsOk() ) { if ( !useMask && blit.GetMask() ) blit.SetMask(NULL); double x = xdest; double y = ydest; double w = dstWidth; double h = dstHeight; // adjust dest rect if source rect is clipped if (subrect.width != subrectOrig.width || subrect.height != subrectOrig.height) { x += (subrect.x - subrectOrig.x) / double(subrectOrig.width) * dstWidth; y += (subrect.y - subrectOrig.y) / double(subrectOrig.height) * dstHeight; w *= double(subrect.width) / subrectOrig.width; h *= double(subrect.height) / subrectOrig.height; } m_graphicContext->DrawBitmap(blit, x, y, w, h); } else { wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") ); retval = false; } if (mode == wxCOMPOSITION_XOR) { m_graphicContext->SetAntialiasMode(formerAa); } } // reset composition m_graphicContext->SetCompositionMode(formerMode); CalcBoundingBox(xdest, ydest); CalcBoundingBox(xdest + dstWidth, ydest + dstHeight); return retval; }
RenderedSubtitle* Renderer::Lookup(const Subtitle* s, const CSize& vs, const CRect& vr) { m_sra.UpdateTarget(vs, vr); if(s->m_text.IsEmpty()) { return NULL; } CRect spdrc = s->m_frame.reference == _T("video") ? vr : CRect(CPoint(0, 0), vs); if(spdrc.IsRectEmpty()) { return NULL; } RenderedSubtitle* rs = NULL; if(m_rsc.Lookup(s->m_name, rs)) { if(!s->m_animated && rs->m_spdrc == spdrc) { return rs; } m_rsc.Invalidate(s->m_name); } const Style& style = s->m_text.GetHead().style; Size scale; scale.cx = (float)spdrc.Width() / s->m_frame.resolution.cx; scale.cy = (float)spdrc.Height() / s->m_frame.resolution.cy; CRect frame; frame.left = (int)(64.0f * (spdrc.left + style.placement.margin.l * scale.cx) + 0.5); frame.top = (int)(64.0f * (spdrc.top + style.placement.margin.t * scale.cy) + 0.5); frame.right = (int)(64.0f * (spdrc.right - style.placement.margin.r * scale.cx) + 0.5); frame.bottom = (int)(64.0f * (spdrc.bottom - style.placement.margin.b * scale.cy) + 0.5); CRect clip; if(style.placement.clip.l == -1) { clip.left = 0; } else { clip.left = (int)(spdrc.left + style.placement.clip.l * scale.cx); } if(style.placement.clip.t == -1) { clip.top = 0; } else { clip.top = (int)(spdrc.top + style.placement.clip.t * scale.cy); } if(style.placement.clip.r == -1) { clip.right = vs.cx; } else { clip.right = (int)(spdrc.left + style.placement.clip.r * scale.cx); } if(style.placement.clip.b == -1) { clip.bottom = vs.cy; } else { clip.bottom = (int)(spdrc.top + style.placement.clip.b * scale.cy); } clip.left = max(clip.left, 0); clip.top = max(clip.top, 0); clip.right = min(clip.right, vs.cx); clip.bottom = min(clip.bottom, vs.cy); scale.cx *= 64; scale.cy *= 64; bool vertical = s->m_direction.primary == _T("down") || s->m_direction.primary == _T("up"); // create glyph paths WCHAR c_prev = 0, c_next; CAutoPtrList<Glyph> glyphs; POSITION pos = s->m_text.GetHeadPosition(); while(pos) { const Text& t = s->m_text.GetNext(pos); LOGFONT lf; memset(&lf, 0, sizeof(lf)); lf.lfCharSet = DEFAULT_CHARSET; _tcscpy_s(lf.lfFaceName, CString(t.style.font.face)); lf.lfHeight = (LONG)(t.style.font.size * scale.cy + 0.5); lf.lfWeight = (LONG)(t.style.font.weight + 0.5); lf.lfItalic = !!t.style.font.italic; lf.lfUnderline = !!t.style.font.underline; lf.lfStrikeOut = !!t.style.font.strikethrough; lf.lfOutPrecision = OUT_TT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = ANTIALIASED_QUALITY; lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE; FontWrapper* font = m_fc.Create(m_hDC, lf); if(!font) { _tcscpy_s(lf.lfFaceName, _T("Arial")); font = m_fc.Create(m_hDC, lf); if(!font) { ASSERT(0); continue; } } HFONT hOldFont = SelectFont(m_hDC, *font); const TEXTMETRIC& tm = font->GetTextMetric(); for(LPCWSTR c = t.str; *c; c++) { CAutoPtr<Glyph> g(DNew Glyph()); g->c = *c; g->style = t.style; g->scale = scale; g->vertical = vertical; g->font = font; c_next = !c[1] && pos ? c_next = s->m_text.GetAt(pos).str[0] : c[1]; Arabic::Replace(g->c, c_prev, c_next); c_prev = c[0]; CSize extent; GetTextExtentPoint32W(m_hDC, &g->c, 1, &extent); ASSERT(extent.cx >= 0 && extent.cy >= 0); if(vertical) { g->spacing = (int)(t.style.font.spacing * scale.cy + 0.5); g->ascent = extent.cx / 2; g->descent = extent.cx - g->ascent; g->width = extent.cy; // TESTME if(g->c == Text::SP) { g->width /= 2; } } else { g->spacing = (int)(t.style.font.spacing * scale.cx + 0.5); g->ascent = tm.tmAscent; g->descent = tm.tmDescent; g->width = extent.cx; } if(g->c == Text::LSEP) { g->spacing = 0; g->width = 0; g->ascent /= 2; g->descent /= 2; } else { GlyphPath* path = m_gpc.Create(m_hDC, font, g->c); if(!path) { ASSERT(0); continue; } g->path = *path; } glyphs.AddTail(g); } SelectFont(m_hDC, hOldFont); } // break glyphs into rows CAutoPtrList<Row> rows; CAutoPtr<Row> row; pos = glyphs.GetHeadPosition(); while(pos) { CAutoPtr<Glyph> g = glyphs.GetNext(pos); if(!row) { row.Attach(DNew Row()); } WCHAR c = g->c; row->AddTail(g); if(c == Text::LSEP || !pos) { rows.AddTail(row); } } // kerning if(s->m_direction.primary == _T("right")) { // || s->m_direction.primary == _T("left") for(POSITION rpos = rows.GetHeadPosition(); rpos; rows.GetNext(rpos)) { Row* r = rows.GetAt(rpos); POSITION gpos = r->GetHeadPosition(); while(gpos) { Glyph* g1 = r->GetNext(gpos); if(!gpos) { break; } Glyph* g2 = r->GetAt(gpos); if(g1->font != g2->font || !g1->style.font.kerning || !g2->style.font.kerning) { continue; } if(int size = g1->font->GetKernAmount(g1->c, g2->c)) { g2->path.MovePoints(CPoint(size, 0)); g2->width += size; } } } } // wrap rows if(s->m_wrap == _T("normal") || s->m_wrap == _T("even")) { int maxwidth = abs((int)(vertical ? frame.Height() : frame.Width())); int minwidth = 0; for(POSITION rpos = rows.GetHeadPosition(); rpos; rows.GetNext(rpos)) { Row* r = rows.GetAt(rpos); POSITION brpos = NULL; if(s->m_wrap == _T("even")) { int fullwidth = 0; for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { const Glyph* g = r->GetAt(gpos); fullwidth += g->width + g->spacing; } fullwidth = abs(fullwidth); if(fullwidth > maxwidth) { maxwidth = fullwidth / ((fullwidth / maxwidth) + 1); minwidth = maxwidth; } } int width = 0; for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { const Glyph* g = r->GetAt(gpos); width += g->width + g->spacing; if(brpos && abs(width) > maxwidth && g->c != Text::SP) { row.Attach(DNew Row()); POSITION next = brpos; r->GetNext(next); do { row->AddHead(r->GetPrev(brpos)); } while(brpos); rows.InsertBefore(rpos, row); while(!r->IsEmpty() && r->GetHeadPosition() != next) { r->RemoveHeadNoReturn(); } g = r->GetAt(gpos = next); width = g->width + g->spacing; } if(abs(width) >= minwidth) { if(g->style.linebreak == _T("char") || g->style.linebreak == _T("word") && g->c == Text::SP) { brpos = gpos; } } } } } // trim rows for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos)) { Row* r = rows.GetAt(pos); while(!r->IsEmpty() && r->GetHead()->c == Text::SP) { r->RemoveHead(); } while(!r->IsEmpty() && r->GetTail()->c == Text::SP) { r->RemoveTail(); } } // calc fill width for each glyph CAtlList<Glyph*> glypsh2fill; int fill_id = 0; int fill_width = 0; for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos)) { Row* r = rows.GetAt(pos); POSITION gpos = r->GetHeadPosition(); while(gpos) { Glyph* g = r->GetNext(gpos); if(!glypsh2fill.IsEmpty() && fill_id && (g->style.fill.id != fill_id || !pos && !gpos)) { int w = (int)(g->style.fill.width * fill_width + 0.5); while(!glypsh2fill.IsEmpty()) { Glyph* g = glypsh2fill.RemoveTail(); fill_width -= g->width; g->fill = w - fill_width; } ASSERT(glypsh2fill.IsEmpty()); ASSERT(fill_width == 0); glypsh2fill.RemoveAll(); fill_width = 0; } fill_id = g->style.fill.id; if(g->style.fill.id) { glypsh2fill.AddTail(g); fill_width += g->width; } } } // calc row sizes and total subtitle size CSize size(0, 0); if(s->m_direction.secondary == _T("left") || s->m_direction.secondary == _T("up")) { ReverseList(rows); } for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos)) { Row* r = rows.GetAt(pos); if(s->m_direction.primary == _T("left") || s->m_direction.primary == _T("up")) { ReverseList(*r); } int w = 0, h = 0; r->width = 0; for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { const Glyph* g = r->GetAt(gpos); w += g->width; if(gpos) { w += g->spacing; } h = max(h, g->ascent + g->descent); r->width += g->width; if(gpos) { r->width += g->spacing; } r->ascent = max(r->ascent, g->ascent); r->descent = max(r->descent, g->descent); r->border = max(r->border, g->GetBackgroundSize()); } for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { Glyph* g = r->GetAt(gpos); g->row_ascent = r->ascent; g->row_descent = r->descent; } if(vertical) { size.cx += h; size.cy = max(size.cy, w); } else { size.cx = max(size.cx, w); size.cy += h; } } // align rows and calc glyph positions rs = DNew RenderedSubtitle(spdrc, clip); CPoint p = GetAlignPoint(style.placement, scale, frame, size); CPoint org = GetAlignPoint(style.placement, scale, frame); // collision detection if(!s->m_animated) { int tlb = !rows.IsEmpty() ? rows.GetHead()->border : 0; int brb = !rows.IsEmpty() ? rows.GetTail()->border : 0; CRect r(p, size); m_sra.GetRect(r, s, style.placement.align, tlb, brb); org += r.TopLeft() - p; p = r.TopLeft(); } CRect subrect(p, size); // continue positioning for(POSITION pos = rows.GetHeadPosition(); pos; rows.GetNext(pos)) { Row* r = rows.GetAt(pos); CSize rsize; rsize.cx = rsize.cy = r->width; if(vertical) { p.y = GetAlignPoint(style.placement, scale, frame, rsize).y; for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { CAutoPtr<Glyph> g = r->GetAt(gpos); g->tl.x = p.x + (int)(g->style.placement.offset.x * scale.cx + 0.5) + r->ascent - g->ascent; g->tl.y = p.y + (int)(g->style.placement.offset.y * scale.cy + 0.5); p.y += g->width + g->spacing; rs->m_glyphs.AddTail(g); } p.x += r->ascent + r->descent; } else { p.x = GetAlignPoint(style.placement, scale, frame, rsize).x; for(POSITION gpos = r->GetHeadPosition(); gpos; r->GetNext(gpos)) { CAutoPtr<Glyph> g = r->GetAt(gpos); g->tl.x = p.x + (int)(g->style.placement.offset.x * scale.cx + 0.5); g->tl.y = p.y + (int)(g->style.placement.offset.y * scale.cy + 0.5) + r->ascent - g->ascent; p.x += g->width + g->spacing; rs->m_glyphs.AddTail(g); } p.y += r->ascent + r->descent; } } // bkg, precalc style.placement.path, transform pos = rs->m_glyphs.GetHeadPosition(); while(pos) { Glyph* g = rs->m_glyphs.GetNext(pos); g->CreateBkg(); g->CreateSplineCoeffs(spdrc); g->Transform(org, subrect); } // merge glyphs (TODO: merge 'fill' too) Glyph* g0 = NULL; pos = rs->m_glyphs.GetHeadPosition(); while(pos) { POSITION cur = pos; Glyph* g = rs->m_glyphs.GetNext(pos); CRect r = g->bbox + g->tl; int size = (int)(g->GetBackgroundSize() + 0.5); int depth = (int)(g->GetShadowDepth() + 0.5); r.InflateRect(size, size); r.InflateRect(depth, depth); r.left >>= 6; r.top >>= 6; r.right = (r.right + 32) >> 6; r.bottom = (r.bottom + 32) >> 6; if((r & clip).IsRectEmpty()) { // clip rs->m_glyphs.RemoveAt(cur); } else if(g0 && g0->style.IsSimilar(g->style)) { // append CPoint o = g->tl - g0->tl; g->path.MovePoints(o); g0->path.types.Append(g->path.types); g0->path.points.Append(g->path.points); g->path_bkg.MovePoints(o); g0->path_bkg.types.Append(g->path_bkg.types); g0->path_bkg.points.Append(g->path_bkg.points); g0->bbox |= g->bbox + o; rs->m_glyphs.RemoveAt(cur); } else { // leave alone g0 = g; } } // rasterize pos = rs->m_glyphs.GetHeadPosition(); while(pos) { rs->m_glyphs.GetNext(pos)->Rasterize(); } // cache m_rsc.Add(s->m_name, rs); m_fc.Flush(); return rs; }
bool wxGCDCImpl::DoStretchBlit( wxCoord xdest, wxCoord ydest, wxCoord dstWidth, wxCoord dstHeight, wxDC *source, wxCoord xsrc, wxCoord ysrc, wxCoord srcWidth, wxCoord srcHeight, wxRasterOperationMode logical_func , bool useMask, wxCoord xsrcMask, wxCoord ysrcMask ) { wxCHECK_MSG( IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid DC") ); wxCHECK_MSG( source->IsOk(), false, wxT("wxGCDC(cg)::DoStretchBlit - invalid source DC") ); if ( logical_func == wxNO_OP ) return true; wxCompositionMode mode = TranslateRasterOp(logical_func); if ( mode == wxCOMPOSITION_INVALID ) { wxFAIL_MSG( wxT("Blitting is not supported with this logical operation.") ); return false; } bool retval = true; wxCompositionMode formerMode = m_graphicContext->GetCompositionMode(); if (m_graphicContext->SetCompositionMode(mode)) { wxAntialiasMode formerAa = m_graphicContext->GetAntialiasMode(); if (mode == wxCOMPOSITION_XOR) { m_graphicContext->SetAntialiasMode(wxANTIALIAS_NONE); } if (xsrcMask == -1 && ysrcMask == -1) { xsrcMask = xsrc; ysrcMask = ysrc; } wxRect subrect(source->LogicalToDeviceX(xsrc), source->LogicalToDeviceY(ysrc), source->LogicalToDeviceXRel(srcWidth), source->LogicalToDeviceYRel(srcHeight)); // if needed clip the subrect down to the size of the source DC wxCoord sw, sh; source->GetSize(&sw, &sh); sw = source->LogicalToDeviceXRel(sw); sh = source->LogicalToDeviceYRel(sh); if (subrect.x + subrect.width > sw) subrect.width = sw - subrect.x; if (subrect.y + subrect.height > sh) subrect.height = sh - subrect.y; wxBitmap blit = source->GetAsBitmap( &subrect ); if ( blit.IsOk() ) { if ( !useMask && blit.GetMask() ) blit.SetMask(NULL); m_graphicContext->DrawBitmap( blit, xdest, ydest, dstWidth, dstHeight); } else { wxFAIL_MSG( wxT("Cannot Blit. Unable to get contents of DC as bitmap.") ); retval = false; } if (mode == wxCOMPOSITION_XOR) { m_graphicContext->SetAntialiasMode(formerAa); } } // reset composition m_graphicContext->SetCompositionMode(formerMode); return retval; }
static FloatRect subrect(IntSize size, float offsetX, float offsetY, float width, float height) { return subrect(IntRect(IntPoint(), size), offsetX, offsetY, width, height); }