bool readIni(const char* filename, ReadIniCallback callback, bool liberal) { if (!callback) { return false; } bool res = false; FileStream file; if ( file.open(filename, FileStream::MODE_READ) ) { size_t size = file.getSize(); char* fileData = new char[size+1]; if (fileData) { file.read(fileData, (u32)size); res = true; } file.close(); if (res) { const char* fileEnd = &fileData[size]; char* readPos = fileData; //now read the data. while (1) { char keyName[512], keyValue[512]; //we are done here. if (!getKey(&readPos, keyName, fileEnd)) { break; } if (!readValue(&readPos, keyValue, fileEnd, liberal)) { break; } //remove preceding or trailing spaces, remove exterior quotation marks. fixupString(keyName); fixupString(keyValue); res &= callback(keyName, keyValue); }; } delete [] fileData; } return res; }
IntRect Bitmap::textSize(const char *str) { guardDisposed(); GUARD_MEGA; TTF_Font *font = p->font->getSdlFont(); std::string fixed = fixupString(str); str = fixed.c_str(); int w, h; TTF_SizeUTF8(font, str, &w, &h); /* If str is one character long, *endPtr == 0 */ const char *endPtr; uint16_t ucs2 = utf8_to_ucs2(str, &endPtr); /* For cursive characters, returning the advance * as width yields better results */ if (p->font->getItalic() && *endPtr == '\0') TTF_GlyphMetrics(font, ucs2, 0, 0, 0, 0, &w); return IntRect(0, 0, w, h); }
bool readCmdLine(const char *cmdline, ReadIniCallback callback) { static char* empty = ""; char* buf = new char[strlen(cmdline)+1]; strcpy(buf,cmdline); char* ps = buf; while(*ps && *ps != ';') { ps++; } *ps = 0; ps = buf; bool res = true; while (*ps && res) { char* parg = NULL; while (*ps && (*ps == ' ' || *ps == '\t')) { ps++; } if (*ps == '"') { parg = ++ps; while(*ps && *ps != '"') { ps++; } if (*ps) { *ps++ = '\0'; } } else if (*ps) { parg = ps; while(*ps && *ps != ' ' && *ps != '\t') { ps++; } if (*ps) { *ps++ = '\0'; } } if (parg) { char* value = parg; for (; *value && *value != '='; value++) {;} if (*value == '=') { *value++ = '\0'; fixupString(parg); fixupString(value); } else { fixupString(parg); value = empty; } res &= callback(parg, value); } } delete buf; return res; }
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(); }