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; } }