From 959831f4ef5a3e797f576c3de08cd65032c997ad Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 18:54:10 +1000 Subject: Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard. --- .../IrrFontTool/newFontTool/CVectorFontTool.h | 2398 ++++++++++---------- 1 file changed, 1199 insertions(+), 1199 deletions(-) (limited to 'libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CVectorFontTool.h') diff --git a/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CVectorFontTool.h b/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CVectorFontTool.h index 05a9c79..c139f3d 100644 --- a/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CVectorFontTool.h +++ b/libraries/irrlicht-1.8/tools/IrrFontTool/newFontTool/CVectorFontTool.h @@ -1,1199 +1,1199 @@ -/* - Vector font tool - Gaz Davidson December 2006-2012 - - I noticed bitmap fonts were taking massive amounts of video memory at reasonable sizes, - so I decided to make a vector font. I always wanted to try converting pixels to triangles... - - And I failed! This is a collection of the ugliest, bloated, most inneficient algorithms - i've ever written, but its kinda working so I'm not changing it. -*/ - -#ifndef __VECTOR_FONT_TOOL_INCLUDED__ -#define __VECTOR_FONT_TOOL_INCLUDED__ - -#include "irrlicht.h" -#include "CFontTool.h" -#include - -using namespace irr; -using namespace video; - -struct STriangleList -{ - core::array positions; - core::array indexes; - - // for adding one triangle list to another, - // these triangles share positions, but dont share triangles - STriangleList& operator+=(STriangleList &other) - { - core::matrix4 m; - core::array map; - map.set_used(other.positions.size()); - - for (u32 i=0; i positions; - - bool isMember(s32 x, s32 y) - { - for (u32 i=0; i h1((f32)(positions[i-1].X - positions[i].X),(f32)(positions[i-1].Y - positions[i].Y)), - h2((f32)(positions[i].X - positions[i+1].X),(f32)(positions[i].Y - positions[i+1].Y)); - h1.normalize(); - h2.normalize(); - - if (h1==h2) // erase the current point - positions.erase(i--); - } - - // level 1- if point1 points at point3, we can skip point2 - // level 2+ allow a deviation of level-1 - - } - - }; - - // contains an array of lines for triangulation - struct SLineList - { - core::array lines; - SLineList() : lines() { } - void addEdge(const SEdge &edge) - { - // adds lines to the buffer - for (u32 i=1; i 0 && - lb.getPointOrientation(l2.start) > 0 && - lc.getPointOrientation(l2.start) > 0) - return true; - //if (la.getPointOrientation(l2.start) < 0 && - // lb.getPointOrientation(l2.start) < 0 && - // lc.getPointOrientation(l2.start) < 0) - // return true; - - core::vector2df out; - //if (la.intersectWith(l2,out)) - // if (out != la.start && out != la.end && - // out != l2.start && out != l2.end) - // return true; - if (lb.intersectWith(l2,out)) - if (!out.equals(lb.start) && !out.equals(lb.end) && - !out.equals(l2.start) && !out.equals(l2.end)) - return true; - if (lc.intersectWith(l2,out)) - if (!out.equals(lc.start) && !out.equals(lc.end) && - !out.equals(l2.start) && !out.equals(l2.end)) - return true; - - // my shit intersection code only works with lines in certain directions :( - if (l2.intersectWith(lb,out)) - if (!out.equals(lb.start) && !out.equals(lb.end) && - !out.equals(l2.start) && !out.equals(l2.end)) - return true; - if (l2.intersectWith(lc,out)) - if (!out.equals(lc.start) && !out.equals(lc.end) && - !out.equals(l2.start) && !out.equals(l2.end)) - return true; - - - if (lb.isPointOnLine(l2.start) && l2.start != lb.start && l2.start != lb.end) - return true; - if (lc.isPointOnLine(l2.start) && l2.start != lc.start && l2.start != lc.end) - return true; - - } - return false; - } - }; - - // an area of adjacent pixels - struct SPixelGroup - { - SPixelGroup(IrrlichtDevice *device) : triangles(), pixelWidth(0), pixelHeight(0), - Device(device) {} - - core::array pixels; - core::array edges; - STriangleList triangles; - core::array ll; - core::array isMemberCache; - s32 pixelWidth; - s32 pixelHeight; - IrrlichtDevice *Device; - - void triangulate() - { - - // find edges in this group - makeEdges(); - - // triangulate the group - makeTriangles(); - - } - - void drawTriangle( core::line2df line, core::vector2df point) - { - //const u32 endt = Device->getTimer()->getTime() + t; - f32 scale = 5; - - - //while(Device->getTimer()->getTime() < endt ) - //{ - Device->run(); - Device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); - for (u32 v=0;vgetVideoDriver()->draw2DLine(st,en, SColor(255,255,255,255)); - } - // draw this triangle - const core::position2di st((s32)(line.start.X*scale)+50, (s32)(line.start.Y*scale)+50); - const core::position2di en((s32)(line.end.X*scale)+50, (s32)(line.end.Y*scale)+50); - const core::position2di p((s32)(point.X*scale)+50, (s32)(point.Y*scale)+50); - Device->getVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); - Device->getVideoDriver()->draw2DLine(en,p, SColor(255,0,255,0)); - Device->getVideoDriver()->draw2DLine(p,st, SColor(255,0,0,255)); - - Device->getVideoDriver()->endScene(); - //} - } - - void makeTriangles() - { - // make lines from edges, because they're easier to deal with - ll.clear(); - for (u32 i=0; i < edges.size(); ++i) - { - SLineList l; - l.addEdge(edges[i]); - ll.push_back(l); - } - // add an extra one for inside edges - SLineList innerlines; - ll.push_back(innerlines); - - // loop through each edge and make triangles - for (u32 i=0; ibestScore) - { - bestScore = score; - bestEdge = k; - bestPoint = j; - } - } - // hopefully we found one - if (bestEdge >= 0 && bestPoint >= 0 && bestScore >= 0.0f) - { - //assert(bestEdge >= 0 && bestPoint >= 0); - //assert(bestScore >= 0.0f); - - core::vector2df point(ll[bestEdge].lines[bestPoint].start.X, ll[bestEdge].lines[bestPoint].start.Y); - - // add it to the triangles list - triangles.add(currentLine.start, currentLine.end, point); - - // add inner lines to the line buffer, but only if they arent in others - - core::line2df la(point,currentLine.start); - core::line2df lb(currentLine.end,point); - - bool found = false; - for (u32 lineno=0;lineno= 3); - - // all edges should be closed - assert(edges[i].positions[0] == edges[i].positions[edges[i].positions.size()-1] ); - } - } - - // adds a line to the edges arrays - void addToEdges(s32 x1, s32 y1, s32 x2, s32 y2) - { - bool found=false; - // loop through each edge - for (u32 i=0; ipixelWidth || y>pixelHeight || x<0 || y<0) - return false; - else - return isMemberCache[pixelWidth*y + x]; - } - - void refreshIsMemberCache() - { - isMemberCache.clear(); - pixelWidth=0; pixelHeight=0; - for (u32 i=0; ipixelWidth) pixelWidth=pixels[i].X; - if (pixels[i].Y>pixelHeight) pixelHeight=pixels[i].Y; - } - pixelWidth+=2; pixelHeight+=2; - isMemberCache.set_used(pixelWidth*pixelHeight+1); - for (u32 i=0; igetTimer()->getTime(); - const u32 endt = stt + t; - - while(device->getTimer()->getTime() < endt ) - { - const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; - - device->run(); - device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); - for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en); - device->getVideoDriver()->draw2DLine(st,ep,video::SColor(255,255,0,0) ); - } - device->getVideoDriver()->endScene(); - } - } - - void drawTriangles(IrrlichtDevice *device, u32 t, s32 scale) - { - const u32 stt = device->getTimer()->getTime(); - const u32 endt = stt + t; - - while(device->getTimer()->getTime() < endt ) - { - const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; - - device->run(); - device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); - for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); - st = core::position2di((s32)(t.positions[t.indexes[v+1]].X*scale)+50,(s32)(t.positions[t.indexes[v+1]].Y*scale)+50); - en = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); - device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,255,0)); - st = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); - en = core::position2di((s32)(t.positions[t.indexes[v+0]].X*scale)+50,(s32)(t.positions[t.indexes[v+0]].Y*scale)+50); - device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,0,255)); - } - device->getVideoDriver()->endScene(); - } - } - - void drawTriLines(IrrlichtDevice *device, u32 t, s32 scale) - { - const u32 endt = device->getTimer()->getTime() + t; - - while(device->getTimer()->getTime() < endt ) - { - device->run(); - device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); - for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); - } - - device->getVideoDriver()->endScene(); - } - } - void drawTri3D(IrrlichtDevice *device, u32 t) - { - for (u32 g=0;g verts; - verts.clear(); - for(u32 v=0; v< t.positions.size(); ++v) - { - verts.push_back(S3DVertex( - -t.positions[v].X, -t.positions[v].Y, -100, - 0,0,1,SColor(255,255,255,255),0,0)); - } - - device->getVideoDriver()->drawIndexedTriangleList(verts.pointer(),verts.size(),t.indexes.pointer(), t.indexes.size()/3 ); - } - } - - - // process all pixels - void findGroups() - { - for (int y=0; y0) // look one behind - { - grp = getRef(x-1,y); - if (grp) found=true; - } - if (y>0) // look above - { - if (x>0) // top left - { - g = getRef(x-1,y-1); - - if (g) - { - if (found) - { - mergeGroups(grp, g); - } - else - { - grp = g; - found = true; - } - } - } - - if (x groups; - core::array groupRefs; - core::array refbuffer; - bool *mem; - IrrlichtDevice *Device; -}; - -// creates a simple vector font from a bitmap from the font tool -class CVectorFontTool -{ -public: - CVectorFontTool(CFontTool *fonttool) : - triangulator(0), FontTool(fonttool), - letterHeight(0), letterWidth(0), triangles() - { - core::map::Iterator it = FontTool->CharMap.getIterator(); - - while(!it.atEnd()) - { - CFontTool::SFontArea &fa = FontTool->Areas[(*it).getValue()]; - - if (fa.rectangle.getWidth() > letterWidth) - letterWidth = fa.rectangle.getWidth(); - if (fa.rectangle.getHeight() > letterHeight) - letterHeight = fa.rectangle.getHeight(); - - it++; - } - - // number of verts is one more than number of pixels because it's a grid of squares - letterWidth++; - letterHeight++; - - // create image memory - imagedata.set_used(letterWidth*letterHeight); - - // create vertex list, set position etc - verts.set_used(letterWidth*letterHeight); - for (s32 y=0; yCharMap.getIterator(); - while(!it.atEnd()) - { - addChar((*it).getKey()); - it++; - } - } - - ~CVectorFontTool() - { - if (triangulator) - delete triangulator; - } - - void addChar(wchar_t thischar) - { - const s32 area = FontTool->CharMap[thischar]; - const CFontTool::SFontArea &fa = FontTool->Areas[area]; - - const s32 img = fa.sourceimage; - const core::rect& r = fa.rectangle; - - // init image memory - IImage *image = FontTool->currentImages[img]; - for (u32 i=0; i < imagedata.size(); ++i) - imagedata[i] = false; - for (s32 y=r.UpperLeftCorner.Y; y < r.LowerRightCorner.Y; ++y) - { - for (s32 x=r.UpperLeftCorner.X; x < r.LowerRightCorner.X ; ++x) - if (image->getPixel(x,y).getBlue() > 0) - { - imagedata[letterWidth*(y-r.UpperLeftCorner.Y) +(x-r.UpperLeftCorner.X)] = true; - } - } - - // get shape areas - triangulator = new CGroupFinder(imagedata.pointer(), letterWidth, letterHeight, FontTool->Device ); - - wprintf(L"Created character '%c' in texture %d\n", thischar, img ); - - //floodfill->drawEdges(FontTool->Device, 500, 3); - //floodfill->drawTriangles(FontTool->Device, 500,30); - //floodfill->drawTriLines(FontTool->Device, 200,3); - - /* - if (area==32 && map == 0) - { - scene::ISceneManager *smgr = FontTool->Device->getSceneManager(); - smgr->addCameraSceneNodeFPS(); - while(FontTool->Device->run()) - { - //floodfill->drawEdges(FontTool->Device, 100, 30); - FontTool->Device->getVideoDriver()->beginScene(true, true, video::SColor(0,200,200,200)); - smgr->drawAll(); - floodfill->drawTri3D(FontTool->Device, 100); - FontTool->Device->getVideoDriver()->endScene(); - } - }*/ - - u32 lastind = triangles.indexes.size(); - - // loop through each shape and add it to the current character... - for (u32 i=0; i < triangulator->groups.size(); ++i) - triangles += triangulator->groups[i].triangles; - - // add character details - charstarts.push_back(lastind); - charlengths.push_back(triangles.indexes.size() - lastind); - chars.push_back(thischar); - } - - bool saveVectorFont(const c8 *filename, const c8 *formatname) - { - IrrlichtDevice *Device = FontTool->Device; - - if (triangles.indexes.size() == 0) - { - Device->getLogger()->log("No vector data to write, aborting."); - return false; - } - - core::stringc fn = filename; - - if (core::stringc(formatname) == core::stringc("xml")) - { - fn += ".xml"; - io::IXMLWriter *writer = FontTool->Device->getFileSystem()->createXMLWriter(fn.c_str()); - - // header and line breaks - writer->writeXMLHeader(); - writer->writeLineBreak(); - - // write info header - writer->writeElement(L"font", false, L"type", L"vector"); - writer->writeLineBreak(); - writer->writeLineBreak(); - - // write each letter - - for (u32 n=0; nCharMap[chars[n]]; - CFontTool::SFontArea &fa = FontTool->Areas[i]; - wchar_t c[2]; - c[0] = chars[n]; - c[1] = L'\0'; - core::stringw area, under, over; - area = core::stringw(fa.rectangle.LowerRightCorner.X- - fa.rectangle.UpperLeftCorner.X); - area += L", "; - area += fa.rectangle.LowerRightCorner.Y- - fa.rectangle.UpperLeftCorner.Y; - - - core::array names; - core::array values; - names.clear(); - values.clear(); - // char - names.push_back(core::stringw(L"c")); - values.push_back(core::stringw(c)); - - // width+height - names.push_back(core::stringw(L"wh")); - values.push_back(area); - - // start - names.push_back(core::stringw(L"st")); - values.push_back(core::stringw(charstarts[n])); - // length - names.push_back(core::stringw(L"len")); - values.push_back(core::stringw(charlengths[n])); - - if (fa.underhang != 0) - { - under = core::stringw(fa.underhang); - names.push_back(core::stringw(L"u")); - values.push_back(under); - } - if (fa.overhang != 0) - { - over = core::stringw(fa.overhang); - names.push_back(core::stringw(L"o")); - values.push_back(over); - } - writer->writeElement(L"c", true, names, values); - - writer->writeLineBreak(); - } - - // write vertex data - core::stringw data, count; - data = L""; - count = core::stringw(triangles.positions.size()); - for (u32 i=0; iwriteElement(L"Vertices", true, L"count", count.c_str(), L"data", data.c_str()); - writer->writeLineBreak(); - - // write index list - data = L""; - count = core::stringw(triangles.indexes.size()); - for (u32 i=0; iwriteElement(L"Indices", true, L"count", count.c_str(), L"data", data.c_str()); - writer->writeLineBreak(); - - writer->writeClosingTag(L"font"); - - writer->drop(); - - Device->getLogger()->log("Font saved."); - return true; - - } - else if (core::stringc(formatname) == core::stringc("bin")) - { - FontTool->Device->getLogger()->log("binary fonts not supported yet, sorry"); - return false; - } - else - { - FontTool->Device->getLogger()->log("unsupported file format, unable to save vector font"); - return false; - } - } - - S3DVertex& getVert(s32 x, s32 y) { return verts[letterWidth*y +x]; } - - core::array verts; - core::array inds; - core::array imagedata; - - core::array charstarts; // start position of each char - core::array charlengths; // index count - core::array chars; // letters - - CGroupFinder* triangulator; - CFontTool* FontTool; - - s32 letterHeight; - s32 letterWidth; - - STriangleList triangles; -}; - -#endif // __VECTOR_FONT_TOOL_INCLUDED__ - +/* + Vector font tool - Gaz Davidson December 2006-2012 + + I noticed bitmap fonts were taking massive amounts of video memory at reasonable sizes, + so I decided to make a vector font. I always wanted to try converting pixels to triangles... + + And I failed! This is a collection of the ugliest, bloated, most inneficient algorithms + i've ever written, but its kinda working so I'm not changing it. +*/ + +#ifndef __VECTOR_FONT_TOOL_INCLUDED__ +#define __VECTOR_FONT_TOOL_INCLUDED__ + +#include "irrlicht.h" +#include "CFontTool.h" +#include + +using namespace irr; +using namespace video; + +struct STriangleList +{ + core::array positions; + core::array indexes; + + // for adding one triangle list to another, + // these triangles share positions, but dont share triangles + STriangleList& operator+=(STriangleList &other) + { + core::matrix4 m; + core::array map; + map.set_used(other.positions.size()); + + for (u32 i=0; i positions; + + bool isMember(s32 x, s32 y) + { + for (u32 i=0; i h1((f32)(positions[i-1].X - positions[i].X),(f32)(positions[i-1].Y - positions[i].Y)), + h2((f32)(positions[i].X - positions[i+1].X),(f32)(positions[i].Y - positions[i+1].Y)); + h1.normalize(); + h2.normalize(); + + if (h1==h2) // erase the current point + positions.erase(i--); + } + + // level 1- if point1 points at point3, we can skip point2 + // level 2+ allow a deviation of level-1 + + } + + }; + + // contains an array of lines for triangulation + struct SLineList + { + core::array lines; + SLineList() : lines() { } + void addEdge(const SEdge &edge) + { + // adds lines to the buffer + for (u32 i=1; i 0 && + lb.getPointOrientation(l2.start) > 0 && + lc.getPointOrientation(l2.start) > 0) + return true; + //if (la.getPointOrientation(l2.start) < 0 && + // lb.getPointOrientation(l2.start) < 0 && + // lc.getPointOrientation(l2.start) < 0) + // return true; + + core::vector2df out; + //if (la.intersectWith(l2,out)) + // if (out != la.start && out != la.end && + // out != l2.start && out != l2.end) + // return true; + if (lb.intersectWith(l2,out)) + if (!out.equals(lb.start) && !out.equals(lb.end) && + !out.equals(l2.start) && !out.equals(l2.end)) + return true; + if (lc.intersectWith(l2,out)) + if (!out.equals(lc.start) && !out.equals(lc.end) && + !out.equals(l2.start) && !out.equals(l2.end)) + return true; + + // my shit intersection code only works with lines in certain directions :( + if (l2.intersectWith(lb,out)) + if (!out.equals(lb.start) && !out.equals(lb.end) && + !out.equals(l2.start) && !out.equals(l2.end)) + return true; + if (l2.intersectWith(lc,out)) + if (!out.equals(lc.start) && !out.equals(lc.end) && + !out.equals(l2.start) && !out.equals(l2.end)) + return true; + + + if (lb.isPointOnLine(l2.start) && l2.start != lb.start && l2.start != lb.end) + return true; + if (lc.isPointOnLine(l2.start) && l2.start != lc.start && l2.start != lc.end) + return true; + + } + return false; + } + }; + + // an area of adjacent pixels + struct SPixelGroup + { + SPixelGroup(IrrlichtDevice *device) : triangles(), pixelWidth(0), pixelHeight(0), + Device(device) {} + + core::array pixels; + core::array edges; + STriangleList triangles; + core::array ll; + core::array isMemberCache; + s32 pixelWidth; + s32 pixelHeight; + IrrlichtDevice *Device; + + void triangulate() + { + + // find edges in this group + makeEdges(); + + // triangulate the group + makeTriangles(); + + } + + void drawTriangle( core::line2df line, core::vector2df point) + { + //const u32 endt = Device->getTimer()->getTime() + t; + f32 scale = 5; + + + //while(Device->getTimer()->getTime() < endt ) + //{ + Device->run(); + Device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); + for (u32 v=0;vgetVideoDriver()->draw2DLine(st,en, SColor(255,255,255,255)); + } + // draw this triangle + const core::position2di st((s32)(line.start.X*scale)+50, (s32)(line.start.Y*scale)+50); + const core::position2di en((s32)(line.end.X*scale)+50, (s32)(line.end.Y*scale)+50); + const core::position2di p((s32)(point.X*scale)+50, (s32)(point.Y*scale)+50); + Device->getVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); + Device->getVideoDriver()->draw2DLine(en,p, SColor(255,0,255,0)); + Device->getVideoDriver()->draw2DLine(p,st, SColor(255,0,0,255)); + + Device->getVideoDriver()->endScene(); + //} + } + + void makeTriangles() + { + // make lines from edges, because they're easier to deal with + ll.clear(); + for (u32 i=0; i < edges.size(); ++i) + { + SLineList l; + l.addEdge(edges[i]); + ll.push_back(l); + } + // add an extra one for inside edges + SLineList innerlines; + ll.push_back(innerlines); + + // loop through each edge and make triangles + for (u32 i=0; ibestScore) + { + bestScore = score; + bestEdge = k; + bestPoint = j; + } + } + // hopefully we found one + if (bestEdge >= 0 && bestPoint >= 0 && bestScore >= 0.0f) + { + //assert(bestEdge >= 0 && bestPoint >= 0); + //assert(bestScore >= 0.0f); + + core::vector2df point(ll[bestEdge].lines[bestPoint].start.X, ll[bestEdge].lines[bestPoint].start.Y); + + // add it to the triangles list + triangles.add(currentLine.start, currentLine.end, point); + + // add inner lines to the line buffer, but only if they arent in others + + core::line2df la(point,currentLine.start); + core::line2df lb(currentLine.end,point); + + bool found = false; + for (u32 lineno=0;lineno= 3); + + // all edges should be closed + assert(edges[i].positions[0] == edges[i].positions[edges[i].positions.size()-1] ); + } + } + + // adds a line to the edges arrays + void addToEdges(s32 x1, s32 y1, s32 x2, s32 y2) + { + bool found=false; + // loop through each edge + for (u32 i=0; ipixelWidth || y>pixelHeight || x<0 || y<0) + return false; + else + return isMemberCache[pixelWidth*y + x]; + } + + void refreshIsMemberCache() + { + isMemberCache.clear(); + pixelWidth=0; pixelHeight=0; + for (u32 i=0; ipixelWidth) pixelWidth=pixels[i].X; + if (pixels[i].Y>pixelHeight) pixelHeight=pixels[i].Y; + } + pixelWidth+=2; pixelHeight+=2; + isMemberCache.set_used(pixelWidth*pixelHeight+1); + for (u32 i=0; igetTimer()->getTime(); + const u32 endt = stt + t; + + while(device->getTimer()->getTime() < endt ) + { + const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; + + device->run(); + device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); + for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en); + device->getVideoDriver()->draw2DLine(st,ep,video::SColor(255,255,0,0) ); + } + device->getVideoDriver()->endScene(); + } + } + + void drawTriangles(IrrlichtDevice *device, u32 t, s32 scale) + { + const u32 stt = device->getTimer()->getTime(); + const u32 endt = stt + t; + + while(device->getTimer()->getTime() < endt ) + { + const f32 phase = f32((device->getTimer()->getTime()-stt) % 500) / 500.0f; + + device->run(); + device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); + for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); + st = core::position2di((s32)(t.positions[t.indexes[v+1]].X*scale)+50,(s32)(t.positions[t.indexes[v+1]].Y*scale)+50); + en = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); + device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,255,0)); + st = core::position2di((s32)(t.positions[t.indexes[v+2]].X*scale)+50,(s32)(t.positions[t.indexes[v+2]].Y*scale)+50); + en = core::position2di((s32)(t.positions[t.indexes[v+0]].X*scale)+50,(s32)(t.positions[t.indexes[v+0]].Y*scale)+50); + device->getVideoDriver()->draw2DLine(st,en, SColor(255,0,0,255)); + } + device->getVideoDriver()->endScene(); + } + } + + void drawTriLines(IrrlichtDevice *device, u32 t, s32 scale) + { + const u32 endt = device->getTimer()->getTime() + t; + + while(device->getTimer()->getTime() < endt ) + { + device->run(); + device->getVideoDriver()->beginScene(true,true,video::SColor(0,0,0,0)); + for (u32 g=0;ggetVideoDriver()->draw2DLine(st,en, SColor(255,255,0,0)); + } + + device->getVideoDriver()->endScene(); + } + } + void drawTri3D(IrrlichtDevice *device, u32 t) + { + for (u32 g=0;g verts; + verts.clear(); + for(u32 v=0; v< t.positions.size(); ++v) + { + verts.push_back(S3DVertex( + -t.positions[v].X, -t.positions[v].Y, -100, + 0,0,1,SColor(255,255,255,255),0,0)); + } + + device->getVideoDriver()->drawIndexedTriangleList(verts.pointer(),verts.size(),t.indexes.pointer(), t.indexes.size()/3 ); + } + } + + + // process all pixels + void findGroups() + { + for (int y=0; y0) // look one behind + { + grp = getRef(x-1,y); + if (grp) found=true; + } + if (y>0) // look above + { + if (x>0) // top left + { + g = getRef(x-1,y-1); + + if (g) + { + if (found) + { + mergeGroups(grp, g); + } + else + { + grp = g; + found = true; + } + } + } + + if (x groups; + core::array groupRefs; + core::array refbuffer; + bool *mem; + IrrlichtDevice *Device; +}; + +// creates a simple vector font from a bitmap from the font tool +class CVectorFontTool +{ +public: + CVectorFontTool(CFontTool *fonttool) : + triangulator(0), FontTool(fonttool), + letterHeight(0), letterWidth(0), triangles() + { + core::map::Iterator it = FontTool->CharMap.getIterator(); + + while(!it.atEnd()) + { + CFontTool::SFontArea &fa = FontTool->Areas[(*it).getValue()]; + + if (fa.rectangle.getWidth() > letterWidth) + letterWidth = fa.rectangle.getWidth(); + if (fa.rectangle.getHeight() > letterHeight) + letterHeight = fa.rectangle.getHeight(); + + it++; + } + + // number of verts is one more than number of pixels because it's a grid of squares + letterWidth++; + letterHeight++; + + // create image memory + imagedata.set_used(letterWidth*letterHeight); + + // create vertex list, set position etc + verts.set_used(letterWidth*letterHeight); + for (s32 y=0; yCharMap.getIterator(); + while(!it.atEnd()) + { + addChar((*it).getKey()); + it++; + } + } + + ~CVectorFontTool() + { + if (triangulator) + delete triangulator; + } + + void addChar(wchar_t thischar) + { + const s32 area = FontTool->CharMap[thischar]; + const CFontTool::SFontArea &fa = FontTool->Areas[area]; + + const s32 img = fa.sourceimage; + const core::rect& r = fa.rectangle; + + // init image memory + IImage *image = FontTool->currentImages[img]; + for (u32 i=0; i < imagedata.size(); ++i) + imagedata[i] = false; + for (s32 y=r.UpperLeftCorner.Y; y < r.LowerRightCorner.Y; ++y) + { + for (s32 x=r.UpperLeftCorner.X; x < r.LowerRightCorner.X ; ++x) + if (image->getPixel(x,y).getBlue() > 0) + { + imagedata[letterWidth*(y-r.UpperLeftCorner.Y) +(x-r.UpperLeftCorner.X)] = true; + } + } + + // get shape areas + triangulator = new CGroupFinder(imagedata.pointer(), letterWidth, letterHeight, FontTool->Device ); + + wprintf(L"Created character '%c' in texture %d\n", thischar, img ); + + //floodfill->drawEdges(FontTool->Device, 500, 3); + //floodfill->drawTriangles(FontTool->Device, 500,30); + //floodfill->drawTriLines(FontTool->Device, 200,3); + + /* + if (area==32 && map == 0) + { + scene::ISceneManager *smgr = FontTool->Device->getSceneManager(); + smgr->addCameraSceneNodeFPS(); + while(FontTool->Device->run()) + { + //floodfill->drawEdges(FontTool->Device, 100, 30); + FontTool->Device->getVideoDriver()->beginScene(true, true, video::SColor(0,200,200,200)); + smgr->drawAll(); + floodfill->drawTri3D(FontTool->Device, 100); + FontTool->Device->getVideoDriver()->endScene(); + } + }*/ + + u32 lastind = triangles.indexes.size(); + + // loop through each shape and add it to the current character... + for (u32 i=0; i < triangulator->groups.size(); ++i) + triangles += triangulator->groups[i].triangles; + + // add character details + charstarts.push_back(lastind); + charlengths.push_back(triangles.indexes.size() - lastind); + chars.push_back(thischar); + } + + bool saveVectorFont(const c8 *filename, const c8 *formatname) + { + IrrlichtDevice *Device = FontTool->Device; + + if (triangles.indexes.size() == 0) + { + Device->getLogger()->log("No vector data to write, aborting."); + return false; + } + + core::stringc fn = filename; + + if (core::stringc(formatname) == core::stringc("xml")) + { + fn += ".xml"; + io::IXMLWriter *writer = FontTool->Device->getFileSystem()->createXMLWriter(fn.c_str()); + + // header and line breaks + writer->writeXMLHeader(); + writer->writeLineBreak(); + + // write info header + writer->writeElement(L"font", false, L"type", L"vector"); + writer->writeLineBreak(); + writer->writeLineBreak(); + + // write each letter + + for (u32 n=0; nCharMap[chars[n]]; + CFontTool::SFontArea &fa = FontTool->Areas[i]; + wchar_t c[2]; + c[0] = chars[n]; + c[1] = L'\0'; + core::stringw area, under, over; + area = core::stringw(fa.rectangle.LowerRightCorner.X- + fa.rectangle.UpperLeftCorner.X); + area += L", "; + area += fa.rectangle.LowerRightCorner.Y- + fa.rectangle.UpperLeftCorner.Y; + + + core::array names; + core::array values; + names.clear(); + values.clear(); + // char + names.push_back(core::stringw(L"c")); + values.push_back(core::stringw(c)); + + // width+height + names.push_back(core::stringw(L"wh")); + values.push_back(area); + + // start + names.push_back(core::stringw(L"st")); + values.push_back(core::stringw(charstarts[n])); + // length + names.push_back(core::stringw(L"len")); + values.push_back(core::stringw(charlengths[n])); + + if (fa.underhang != 0) + { + under = core::stringw(fa.underhang); + names.push_back(core::stringw(L"u")); + values.push_back(under); + } + if (fa.overhang != 0) + { + over = core::stringw(fa.overhang); + names.push_back(core::stringw(L"o")); + values.push_back(over); + } + writer->writeElement(L"c", true, names, values); + + writer->writeLineBreak(); + } + + // write vertex data + core::stringw data, count; + data = L""; + count = core::stringw(triangles.positions.size()); + for (u32 i=0; iwriteElement(L"Vertices", true, L"count", count.c_str(), L"data", data.c_str()); + writer->writeLineBreak(); + + // write index list + data = L""; + count = core::stringw(triangles.indexes.size()); + for (u32 i=0; iwriteElement(L"Indices", true, L"count", count.c_str(), L"data", data.c_str()); + writer->writeLineBreak(); + + writer->writeClosingTag(L"font"); + + writer->drop(); + + Device->getLogger()->log("Font saved."); + return true; + + } + else if (core::stringc(formatname) == core::stringc("bin")) + { + FontTool->Device->getLogger()->log("binary fonts not supported yet, sorry"); + return false; + } + else + { + FontTool->Device->getLogger()->log("unsupported file format, unable to save vector font"); + return false; + } + } + + S3DVertex& getVert(s32 x, s32 y) { return verts[letterWidth*y +x]; } + + core::array verts; + core::array inds; + core::array imagedata; + + core::array charstarts; // start position of each char + core::array charlengths; // index count + core::array chars; // letters + + CGroupFinder* triangulator; + CFontTool* FontTool; + + s32 letterHeight; + s32 letterWidth; + + STriangleList triangles; +}; + +#endif // __VECTOR_FONT_TOOL_INCLUDED__ + -- cgit v1.1