Esempio n. 1
0
void
GLHelper::drawTextBox(const std::string& text, const Position& pos,
                      const double layer, const double size,
                      const RGBColor& txtColor, const RGBColor& bgColor, const RGBColor& borderColor,
                      const double angle,
                      const double relBorder,
                      const double relMargin) {
    if (!initFont()) {
        return;
    };
    if (bgColor.alpha() != 0) {
        const double boxAngle = 90;
        const double stringWidth = size / myFontSize * fonsTextBounds(myFont, 0, 0, text.c_str(), nullptr, nullptr);
        const double borderWidth = size * relBorder;
        const double boxHeight = size * (0.32 + 0.6 * relMargin);
        const double boxWidth = stringWidth + size * relMargin;
        glPushMatrix();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glTranslated(pos.x(), pos.y(), layer);
        glRotated(-angle, 0, 0, 1);
        Position left(-boxWidth * 0.5, 0);
        setColor(borderColor);
        drawBoxLine(left, boxAngle, boxWidth, boxHeight);
        left.add(borderWidth * 1.5, 0);
        setColor(bgColor);
        glTranslated(0, 0, 0.01);
        drawBoxLine(left, boxAngle, boxWidth - 3 * borderWidth, boxHeight - 2 * borderWidth);
        glPopMatrix();
    }
    drawText(text, pos, layer + 0.02, size, txtColor, angle);
}
Esempio n. 2
0
ofRectangle ofxFontStash2::getTextBounds( const string &text, const ofxFontStashStyle &style, const float x, const float y ){
	applyStyle(style);
	float bounds[4]={0,0,0,0};
	int advance = fonsTextBounds( fs, x*pixelDensity, y*pixelDensity, text.c_str(), NULL, bounds );
	advance/=pixelDensity;
	bounds[0]/=pixelDensity;
	bounds[1]/=pixelDensity;
	bounds[2]/=pixelDensity;
	bounds[3]/=pixelDensity;
	// here we use the "text advance" instead of the width of the rectangle,
	// because this includes spaces at the end correctly (the text bounds "x" and "x " are the same,
	// the text advance isn't). 
	return ofRectangle(bounds[0],bounds[1],advance,bounds[3]-bounds[1]);
}
Esempio n. 3
0
int Asset_TextWidth(AssetHandle assetHandle, const char *string, float scale) {
	Asset *asset = Asset_Get(ASSET_ANY, assetHandle);

	assert(asset != nullptr);

	if (asset->type != ASSET_BITMAPFONT && asset->type != ASSET_FONT) {
		Con_Errorf(ERR_GAME, "asset %s not font or bmpfont", asset->name);
		return -1;
	}

	int hnd;
	if (asset->type == ASSET_BITMAPFONT) {
		BitmapFont_t *fnt = (BitmapFont_t*)asset->resource;
		hnd = fnt->hnd;	
	} else {
		TTFFont_t *fnt = (TTFFont_t*)asset->resource;
		hnd = fnt->hnd;
	}

	fonsSetFont(ctx, hnd);
	fonsSetSize(ctx, scale);
	return (int) fonsTextBounds(ctx, 0, 0, string, nullptr, nullptr);
}
Esempio n. 4
0
void LikertHCI::initializeText(int threadId, FONScontext* fs, int fontNormal, int lineCount, float border, std::shared_ptr<GLSLProgram> shader, float textSize, const std::vector<std::string> &texts, std::string texKey, std::vector<std::vector<std::shared_ptr<Texture> > > &textures, std::vector<std::vector<glm::dvec2> > &sizes)
{
	float sx, sy, lh = 0;
	unsigned int white = glfonsRGBA(255,255,255,255);
	unsigned int gray = glfonsRGBA(81, 76, 76, 255);

	fonsClearState(fs);
	fonsSetSize(fs, textSize);
	fonsSetFont(fs, fontNormal);
	fonsSetColor(fs, white);
	fonsSetAlign(fs, FONS_ALIGN_CENTER | FONS_ALIGN_TOP);
	fonsVertMetrics(fs, NULL, NULL, &lh);

	for(int i=0; i < texts.size(); i++) {

		std::stringstream ss(texts[i]);
		std::string line;
		std::vector<std::string> lines;

		float maxWidth = 0;
		while(std::getline(ss, line, '\n')){
			float width = fonsTextBounds(fs, line.c_str(), NULL, NULL);
			if (width > maxWidth) {
				maxWidth = width;
			}
			lines.push_back(line);
		}

		sx = maxWidth + (1.0f*border);
		sy = border;
		if (lineCount > lines.size()) {
			sy += lh * (lineCount - lines.size()) * 0.5;
		}
		float height = lh*lineCount+2.0*border;


		std::shared_ptr<Texture> depthTexture = Texture::createEmpty("depthTex", sx, height, 1, 1, false, GL_TEXTURE_2D, GL_DEPTH_COMPONENT32F);
		depthTexture->setTexParameteri(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		depthTexture->setTexParameteri(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		depthTexture->setTexParameteri(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		depthTexture->setTexParameteri(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture->getID(), 0);

		textures[threadId][i] = Texture::createEmpty("colorTex", sx, height, 1, 4, false, GL_TEXTURE_2D, GL_RGBA8);
		textures[threadId][i]->setTexParameteri(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		textures[threadId][i]->setTexParameteri(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		textures[threadId][i]->setTexParameteri(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		textures[threadId][i]->setTexParameteri(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		textures[threadId][i]->setTexParameterf(GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0);
		glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textures[threadId][i]->getID(), 0);
			
		GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
		switch(status) {
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
			assert(false);
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
			assert(false);
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
			assert(false);
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
			assert(false);
			break;
		case GL_FRAMEBUFFER_UNSUPPORTED:
			assert(false);
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
			assert(false);
			break;
		default:
			break;
		}
		assert(status == GL_FRAMEBUFFER_COMPLETE);

		sizes[threadId].push_back(glm::dvec2(sx, height));

		glViewport(0,0, sx, height);
		glClear(GL_COLOR_BUFFER_BIT);

		shader->setUniform("projection_mat", glm::ortho(0., (double)sx, (double)height, 0., -1., 1.));
		shader->setUniform("view_mat", glm::dmat4(1.0));
		shader->setUniform("model_mat", glm::dmat4(1.0));
		shader->setUniform("has_lambertian_texture", false);

		glDisable(GL_DEPTH_TEST);


		// Draw the darker interior quad so we get a white border around the outside from the clear color
		float rim = border/4.0f;

		GLfloat vertices[]  = {rim, height-rim,    sx-rim, height-rim,  rim, rim,  sx-rim, rim};
		GLfloat texCoords[] = { 0, 1,   1, 1,  1, 0,  0, 0 };
		GLfloat colors[]  = { 0.32, 0.3, 0.3, 1.0,   0.32, 0.3, 0.3, 1.0,   0.32, 0.3, 0.3, 1.0,   0.32, 0.3, 0.3, 1.0};

		// create the vao
		GLuint vaoID = 0;
		glGenVertexArrays(1, &vaoID);
		glBindVertexArray(vaoID);

		GLuint quadVBO = 0;
		glGenBuffers(1, &quadVBO);
		glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(texCoords)+sizeof(colors), 0, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);                             // copy vertices starting from 0 offest
		glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(texCoords), texCoords);                // copy texCoords after vertices
		glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(texCoords), sizeof(colors), colors);  // copy colours after normals

		// set up vertex attributes
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)sizeof(vertices));
		glEnableVertexAttribArray(2);
		glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(vertices)+sizeof(texCoords)));

		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		glBindVertexArray(0);
		glDeleteBuffers(1, &quadVBO);
		glDeleteVertexArrays(1, &vaoID);

		shader->setUniform("has_lambertian_texture", true);
		glActiveTexture(GL_TEXTURE0);
		shader->setUniform("lambertian_texture", 0);

		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		for(int j=0; j < lines.size(); j++) { 
			std::string text = boost::replace_all_copy(lines[j], "_", " ");
			fonsDrawText(fs, sx/2.0, sy, text.c_str(), NULL);
			sy += lh;
		}

		glDisable(GL_BLEND);

		textures[threadId][i]->generateMipMaps();
		std::string textureKey = texKey + texts[i];
		texMan->setTextureEntry(threadId, textureKey, textures[threadId][i]);

		depthTexture.reset();
	}
}
Esempio n. 5
0
const vector<StyledLine> ofxFontStash2::layoutLines(const vector<StyledText> &blocks, float targetWidth, bool debug ){
	float x = 0;
	float y = 0;
	if (targetWidth < 0) return vector<StyledLine>();
	float xx = x;
	float yy = y;
	
	TS_START_NIF("split words");
	vector<SplitTextBlock> words = splitWords(blocks);
	TS_STOP_NIF("split words");
	
	if (words.size() == 0) return vector<StyledLine>();
	
	vector<StyledLine> lines;
	
	// here we create the first line. a few things to note:
	// - in general, like in a texteditor, the line exists first, then content is added to it.
	// - 'line' here refers to the visual representation. even a line with no newline (\n) can span multiple lines
	lines.push_back(StyledLine());
	
	ofxFontStashStyle currentStyle;
	currentStyle.fontSize = -1; // this makes sure the first style is actually applied, even if it's the default style
		
	float lineWidth = 0;
	int wordsThisLine = 0;
	
	vector<float> lineHeigts;
	float currentLineH = 0;
	
	float bounds[4];
	float dx;
	LineElement le;
	
	TS_START("walk words");
	for(int i = 0; i < words.size(); i++){
		StyledLine &currentLine = lines.back();
		
		//TS_START_ACC("word style");
		if(words[i].styledText.style.valid && currentStyle != words[i].styledText.style ){
			//cout << "   new style!" << endl;
			currentStyle = words[i].styledText.style;
			if(applyStyle(currentStyle)){
				fonsVertMetrics(fs, NULL, NULL, &currentLineH);
				currentLineH/=pixelDensity;
			}else{
				ofLogError() << "no style font defined!";
			}
		}
		//TS_STOP_ACC("word style");
		
		bool stayOnCurrentLine = true;
		
		if( words[i].type == SEPARATOR_INVISIBLE && words[i].styledText.text == "\n" ){
			stayOnCurrentLine = false;
			dx = 0;
			
			// add a zero-width enter mark. this is used to keep track
			// of the vertical spacing of empty lines.
			le = LineElement(words[i], ofRectangle(xx,yy,0,currentLineH));
			le.baseLineY = yy;
			le.x = xx;
			le.lineHeight = currentLineH;
			currentLine.elements.push_back(le);
			
			float lineH = calcLineHeight(currentLine);
			currentLine.lineH = lineH;
			currentLine.lineW = xx - x + dx;
			
			// no!
			//i--; //re-calc dimensions of this word on a new line!
			yy += lineH;
			
			lineWidth = 0;
			wordsThisLine = 0;
			xx = x;
			lines.push_back(StyledLine());
			continue;
		}
		else{
			//TS_START_ACC("fonsTextBounds");
			// applyStyle() already upscaled the font size for the display resolution.
			// Here we do the same for x/y.
			// The result gets the inverse treatment.
			dx = fonsTextBounds(	fs,
								xx*pixelDensity,
								yy*pixelDensity,
								words[i].styledText.text.c_str(),
								NULL,
								&bounds[0]
								)/pixelDensity;
			bounds[0]/=pixelDensity;
			bounds[1]/=pixelDensity;
			bounds[2]/=pixelDensity;
			bounds[3]/=pixelDensity;
			//TS_STOP_ACC("fonsTextBounds");
			
			//hansi: using dx instead of bounds[2]-bounds[0]
			//dx is the right size for spacing out text. bounds give exact area of the char, which isn't so useful here.
			ofRectangle where = ofRectangle(bounds[0], bounds[1] , dx, bounds[3] - bounds[1]);
			
			le = LineElement(words[i], where);
			le.baseLineY = yy;
			le.x = xx;
			le.lineHeight = currentLineH;
			
			float nextWidth = lineWidth + dx;
			
			//if not wider than targetW
			// ||
			//this is the 1st word in this line but even that doesnt fit
			stayOnCurrentLine = nextWidth < targetWidth || (wordsThisLine == 0 && (nextWidth >= targetWidth));
			
		}
		
		if (stayOnCurrentLine){
			
			//TS_START_ACC("stay on line");
			currentLine.elements.push_back(le);
			lineWidth += dx;
			xx += dx;
			wordsThisLine++;
			//TS_STOP_ACC("stay on line");
			
		} else if( words[i].type == SEPARATOR_INVISIBLE && words[i].styledText.text == " " ){
			// ignore spaces when moving into the next line!
			continue;
		} else{ //too long, start a new line
			
			//TS_START_ACC("new line");
			//calc height for this line - taking in account all words in the line
			float lineH = lineHeightMultiplier * calcLineHeight(currentLine);
			currentLine.lineH = lineH;
			currentLine.lineW = xx - x;
			
			i--; //re-calc dimensions of this word on a new line!
			yy += lineH;
			
			lineWidth = 0;
			wordsThisLine = 0;
			xx = x;
			lines.push_back(StyledLine());
			//TS_STOP_ACC("new line");
		}
	}

	//TS_START_ACC("last line");
	// update dimensions of the last line
	StyledLine &currentLine = lines.back();
	if( currentLine.elements.size() == 0 ){
		// but at least one spacing character, so we have a line height.
		le = LineElement(SplitTextBlock(SEPARATOR_INVISIBLE,"",currentStyle), ofRectangle(xx,yy,0,currentLineH));
		le.baseLineY = yy;
		le.x = xx;
		le.lineHeight = currentLineH;
		currentLine.elements.push_back(le);
	}
	
	float lineH = calcLineHeight(currentLine);
	currentLine.lineH = lineH;
	currentLine.lineW = xx - x + dx;
	
	//TS_STOP_ACC("last line");

	TS_STOP("walk words");
	
	return lines; 
}