void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color)
{
    state().m_shadowOffset = FloatSize(width, height);
    state().m_shadowBlur = blur;
    state().m_shadowColor = color;
    applyShadow();
}
void CanvasRenderingContext2D::clearShadow()
{
    state().m_shadowOffset = FloatSize();
    state().m_shadowBlur = 0;
    state().m_shadowColor = "";
    applyShadow();
}
void CanvasRenderingContext2D::setShadowColor(const String& color)
{
    state().m_shadowColor = color;
    applyShadow();
}
void CanvasRenderingContext2D::setShadowBlur(float blur)
{
    state().m_shadowBlur = blur;
    applyShadow();
}
void CanvasRenderingContext2D::setShadowOffsetY(float y)
{
    state().m_shadowOffset.setHeight(y);
    applyShadow();
}
void CanvasRenderingContext2D::setShadowOffsetX(float x)
{
    state().m_shadowOffset.setWidth(x);
    applyShadow();
}
Пример #7
0
void Bitmap::drawText(const IntRect &rect, const char *str, int align)
{
	guardDisposed();

	GUARD_MEGA;

	std::string fixed = fixupString(str);
	str = fixed.c_str();

	if (*str == '\0')
		return;

	if (str[0] == ' ' && str[1] == '\0')
		return;

	TTF_Font *font = p->font->getSdlFont();
	const Color &fontColor = p->font->getColor();
	const Color &outColor = p->font->getOutColor();

	SDL_Color c = fontColor.toSDLColor();
	c.a = 255;

	float txtAlpha = fontColor.norm.w;

	SDL_Surface *txtSurf;

	if (shState->rtData().config.solidFonts)
		txtSurf = TTF_RenderUTF8_Solid(font, str, c);
	else
		txtSurf = TTF_RenderUTF8_Blended(font, str, c);

	p->ensureFormat(txtSurf, SDL_PIXELFORMAT_ABGR8888);

	int rawTxtSurfH = txtSurf->h;

	if (p->font->getShadow())
		applyShadow(txtSurf, *p->format, c);

	/* outline using TTF_Outline and blending it together with SDL_BlitSurface
	 * FIXME: outline is forced to have the same opacity as the font color */
	if (p->font->getOutline())
	{
		SDL_Color co = outColor.toSDLColor();
		co.a = 255;
		SDL_Surface *outline;
		/* set the next font render to render the outline */
		TTF_SetFontOutline(font, OUTLINE_SIZE);
		if (shState->rtData().config.solidFonts)
			outline = TTF_RenderUTF8_Solid(font, str, co);
		else
			outline = TTF_RenderUTF8_Blended(font, str, co);

		p->ensureFormat(outline, SDL_PIXELFORMAT_ABGR8888);
		SDL_Rect outRect = {OUTLINE_SIZE, OUTLINE_SIZE, txtSurf->w, txtSurf->h}; 

		SDL_SetSurfaceBlendMode(txtSurf, SDL_BLENDMODE_BLEND);
		SDL_BlitSurface(txtSurf, NULL, outline, &outRect);
		SDL_FreeSurface(txtSurf);
		txtSurf = outline;
		/* reset outline to 0 */
		TTF_SetFontOutline(font, 0);
	}

	int alignX = rect.x;

	switch (align)
	{
	default:
	case Left :
		break;

	case Center :
		alignX += (rect.w - txtSurf->w) / 2;
		break;

	case Right :
		alignX += rect.w - txtSurf->w;
		break;
	}

	if (alignX < rect.x)
		alignX = rect.x;

	int alignY = rect.y + (rect.h - rawTxtSurfH) / 2;

	float squeeze = (float) rect.w / txtSurf->w;

	if (squeeze > 1)
		squeeze = 1;

	FloatRect posRect(alignX, alignY, txtSurf->w * squeeze, txtSurf->h);

	Vec2i gpTexSize;
	shState->ensureTexSize(txtSurf->w, txtSurf->h, gpTexSize);

	bool fastBlit = !p->touchesTaintedArea(posRect) && txtAlpha == 1.0f;

	if (fastBlit)
	{
		if (squeeze == 1.0f && !shState->config().subImageFix)
		{
			/* Even faster: upload directly to bitmap texture.
			 * We have to make sure the posRect lies within the texture
			 * boundaries or texSubImage will generate errors.
			 * If it partly lies outside bounds we have to upload
			 * the clipped visible part of it. */
			SDL_Rect btmRect;
			btmRect.x = btmRect.y = 0;
			btmRect.w = width();
			btmRect.h = height();

			SDL_Rect txtRect;
			txtRect.x = posRect.x;
			txtRect.y = posRect.y;
			txtRect.w = posRect.w;
			txtRect.h = posRect.h;

			SDL_Rect inters;

			/* If we have no intersection at all,
			 * there's nothing to upload to begin with */
			if (SDL_IntersectRect(&btmRect, &txtRect, &inters))
			{
				bool subImage = false;
				int subSrcX = 0, subSrcY = 0;

				if (inters.w != txtRect.w || inters.h != txtRect.h)
				{
					/* Clip the text surface */
					subSrcX = inters.x - txtRect.x;
					subSrcY = inters.y - txtRect.y;
					subImage = true;

					posRect.x = inters.x;
					posRect.y = inters.y;
					posRect.w = inters.w;
					posRect.h = inters.h;
				}

				TEX::bind(p->gl.tex);

				if (!subImage)
				{
					TEX::uploadSubImage(posRect.x, posRect.y,
					                    posRect.w, posRect.h,
					                    txtSurf->pixels, GL_RGBA);
				}
				else
				{
					GLMeta::subRectImageUpload(txtSurf->w, subSrcX, subSrcY,
					                           posRect.x, posRect.y,
					                           posRect.w, posRect.h,
					                           txtSurf, GL_RGBA);
					GLMeta::subRectImageEnd();
				}
			}
		}
		else
		{
			/* Squeezing involved: need to use intermediary TexFBO */
			TEXFBO &gpTF = shState->gpTexFBO(txtSurf->w, txtSurf->h);

			TEX::bind(gpTF.tex);
			TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_RGBA);

			GLMeta::blitBegin(p->gl);
			GLMeta::blitSource(gpTF);
			GLMeta::blitRectangle(IntRect(0, 0, txtSurf->w, txtSurf->h),
			                      posRect, true);
			GLMeta::blitEnd();
		}
	}
	else
	{
		/* Aquire a partial copy of the destination
		 * buffer we're about to render to */
		TEXFBO &gpTex2 = shState->gpTexFBO(posRect.w, posRect.h);

		GLMeta::blitBegin(gpTex2);
		GLMeta::blitSource(p->gl);
		GLMeta::blitRectangle(posRect, Vec2i());
		GLMeta::blitEnd();

		FloatRect bltRect(0, 0,
		                  (float) (gpTexSize.x * squeeze) / gpTex2.width,
		                  (float) gpTexSize.y / gpTex2.height);

		BltShader &shader = shState->shaders().blt;
		shader.bind();
		shader.setTexSize(gpTexSize);
		shader.setSource();
		shader.setDestination(gpTex2.tex);
		shader.setSubRect(bltRect);
		shader.setOpacity(txtAlpha);

		shState->bindTex();
		TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_RGBA);
		TEX::setSmooth(true);

		Quad &quad = shState->gpQuad();
		quad.setTexRect(FloatRect(0, 0, txtSurf->w, txtSurf->h));
		quad.setPosRect(posRect);

		p->bindFBO();
		p->pushSetViewport(shader);

		p->blitQuad(quad);

		p->popViewport();
	}

	SDL_FreeSurface(txtSurf);
	p->addTaintedArea(posRect);

	p->onModified();
}