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;
    }
}
Пример #3
0
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 };
}
Пример #5
0
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);
			}
		}
	}
}
Пример #6
0
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;
}
Пример #7
0
	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;
	}
Пример #8
0
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);
}