Example #1
0
Mesh::Mesh(string filename, bool ccw):
    mRot(0,0,0),
    mPos(0,0,0),
    mAABB(BVL_SIZE(BVL)),
    mAABBTriangles(BVL_SIZE(BVL)),
    mSphere(BVL_SIZE(BVL)),
    mSphereTriangles(BVL_SIZE(BVL))
{
    clock_t t = clock();
    loadObj(filename, mVertices, mTriangles, ccw);
    createTriangleLists();
    createBoundingVolHierarchy();
    centerAlign();
    createNormals();
    calculateVolume();
    printf ("Mesh loading took:\t%4.2f sec | %d triangles \n", ((float)clock()-t)/CLOCKS_PER_SEC, mTriangles.size());
    for (int blevel=0; blevel<=BVL; blevel++)
        printf("Coverage Level %d: AABB %4.2f%%, Sphere %4.2f%% \n", blevel, 100*AABBCover[blevel], 100*sphereCover[blevel]);

}
/**
 * layout a text with provided parameters
 *
 * @param cr:			the cairo instance
 * @param text:			the text to layout
 * @param font:			the font to use to layout to
 * @param size:			the font size size of each char to layout
 * @param bounds:		the bounds of layouting
 * @param alignment:	the text alignment on cairo's buffer
 * @param layout:		the returned layouted text instance
 * @param-opt breakOnOverflow:	break the layouting if size overflow the provided bounds
 */
void TextLayouter::layout(cairo_t *cr, const char *text, Font_t *font, int32_t size, Rectangle bounds, const TextAlignment &alignment, LayoutedText *layout, bool breakOnOverflow)
{
	// check font validity
	if (!font) return;

	// get text length
	size_t textLen = strlen(text);

	// starting coordinates
	int x = bounds.x;
	int y = bounds.y;
	int lineStartX = x;

	// created the scaled font face
	cairo_set_font_face(cr, font->getFace());
	cairo_set_font_size(cr, size);
	cairo_scaled_font_t *scaledFace = cairo_get_scaled_font(cr);

	int line = 0;
	int lineHeight = size;

	// create glyphs for the text
	cairo_glyph_t *previousGlyphBuffer = layout->glyphBuffer;
	cairo_text_cluster_t *previousClusterBuffer = layout->clusterBuffer;

	cairo_text_cluster_flags_t clusterFlags;
	cairo_status_t stat = cairo_scaled_font_text_to_glyphs(scaledFace, 0, 0, text, textLen, &layout->glyphBuffer, &layout->glyphCount, &layout->clusterBuffer, &layout->clusterCount, &clusterFlags);

	// free old buffer
	if (previousGlyphBuffer != nullptr && layout->glyphBuffer != previousGlyphBuffer) free(previousGlyphBuffer);
	if (previousClusterBuffer != nullptr && layout->clusterBuffer != previousClusterBuffer) free(previousClusterBuffer);

	// clear layout entries
	layout->positions.clear();

	// perform layouting
	if (stat == CAIRO_STATUS_SUCCESS)
	{
		// positions in bytes and glyphs
		size_t bytePos = 0;
		size_t glyphPos = 0;

		// text extents
		cairo_text_extents_t extents;
		for (int i = 0; i < layout->clusterCount; i++)
		{
			cairo_text_cluster_t *cluster = &layout->clusterBuffer[i];
			cairo_glyph_t *glyphs = &layout->glyphBuffer[glyphPos];

			// create new position
			PositionedGlyph positioned;
			positioned.glyph = glyphs;
			positioned.glyphCount = cluster->num_glyphs;
			cairo_scaled_font_glyph_extents(scaledFace, positioned.glyph, positioned.glyphCount, &extents);

			positioned.advance.x = extents.x_advance;
			positioned.advance.y = extents.y_advance;
			positioned.size.width = extents.width;
			positioned.size.height = extents.height;

			// check if newline
			bool isNewline = false;
			if (cluster->num_bytes == 1 && text[bytePos] == '\n') isNewline = true;
			bool invisible = false;

			// Wouldn't match in line or is break character? Start next line
			if (isNewline || (breakOnOverflow && (x + positioned.size.width > bounds.width)))
			{
				if (isNewline) invisible = true;
				if (alignment == TextAlignment::RIGHT) rightAlign(layout, line, x - lineStartX, bounds);
				else if (alignment == TextAlignment::CENTER) centerAlign(layout, line, x - lineStartX, bounds);

				++line;
				x = bounds.x;
				lineStartX = x;
				y += lineHeight;
			}

			if (!invisible)
			{
				// Position
				positioned.line = line;
				positioned.position.x = x;
				positioned.position.y = y + lineHeight;

				// Add position
				layout->positions.push_back(positioned);

				// Jump to next
				x += positioned.advance.x;
			}

			// increase positions
			glyphPos += cluster->num_glyphs;
			bytePos += cluster->num_bytes;
		}
	}

	if (alignment == TextAlignment::RIGHT) rightAlign(layout, line, x - lineStartX, bounds);
	else if (alignment == TextAlignment::CENTER) centerAlign(layout, line, x - lineStartX, bounds);

	// Set text bounds
	#define BOUNDS_EMPTY 0xFFFFFF
	int tbTop = BOUNDS_EMPTY;
	int tbLeft = BOUNDS_EMPTY;
	int tbRight = 0;
	int tbBottom = 0;

	for (PositionedGlyph &p : layout->positions)
	{
		if (p.position.x < tbLeft) tbLeft = p.position.x;
		if (p.position.y < tbTop) tbTop = p.position.y;

		// get extents again
		int r = p.position.x + p.size.width;
		if (r > tbRight) tbRight = r;

		int b = p.position.y + p.size.height;
		if (b > tbBottom) tbBottom = b;
	}

	if (tbTop != BOUNDS_EMPTY && tbLeft != BOUNDS_EMPTY)
	{
		layout->textBounds.x = tbLeft;
		layout->textBounds.y = tbTop;
		layout->textBounds.width = tbRight - tbLeft;
		layout->textBounds.height = tbBottom - tbTop;
	}
}