diff --git a/components/nvidia-widgets/doc/compile.bat b/components/nvidia-widgets/doc/compile.bat index b5c4057f9..df0a1d0ae 100644 --- a/components/nvidia-widgets/doc/compile.bat +++ b/components/nvidia-widgets/doc/compile.bat @@ -1,6 +1,6 @@ set path=%path%;H:\other\graphviz\bin -fpclasschart --input=../src/nvwidgets/nvWidgets.pas --input=../src/nvwidgets/nvglwidgets.pas --input=../src/nvwidgets/nvglutwidgets.pas --input=../src/nvglutils/nvshaderutils.pas --format=graphviz --output=nvwidgets.dot +fpclasschart --input=../src/nvwidgets/nvWidgets.pas --input=../src/nvwidgets/nvglwidgets.pas --input=../src/nvwidgets/nvglutwidgets.pas --input=../src/nvglutils/nvshaderutils.pas --input=../src/gl/glfreetype.pas --format=graphviz --output=nvwidgets.dot dot -Tpng nvwidgets.dot > ./images/nvwidgets.png @@ -10,7 +10,7 @@ del nvwidgets.dot del *.chm ::create chm documentation -fpdoc --package=nvidia-widgets --descr=nvwidgets.xml --input=../src/nvwidgets/nvWidgets.pas --descr=nvglwidgets.xml --input=../src/nvwidgets/nvglwidgets.pas --descr=nvglutwidgets.xml --input=../src/nvwidgets/nvglutwidgets.pas --descr=nvshaderutils.xml --input=../src/nvglutils/nvshaderutils.pas --css-file=fpdoc.css --format=chm --output=nvwidgets.chm +fpdoc --package=nvidia-widgets --descr=nvwidgets.xml --input=../src/nvwidgets/nvWidgets.pas --descr=nvglwidgets.xml --input=../src/nvwidgets/nvglwidgets.pas --descr=nvglutwidgets.xml --input=../src/nvwidgets/nvglutwidgets.pas --descr=nvshaderutils.xml --input=../src/nvglutils/nvshaderutils.pas --descr=glfreetype.xml --input=../src/gl/glfreetype.pas --css-file=fpdoc.css --format=chm --output=nvwidgets.chm ::delete old html documentation del *.html @@ -20,4 +20,4 @@ del /Q /S nvglwidgets\*.html del /Q /S nvshaderutils\*.html ::create html documentation -fpdoc --package=nvidia-widgets --descr=nvwidgets.xml --input=../src/nvwidgets/nvWidgets.pas --descr=nvglwidgets.xml --input=../src/nvwidgets/nvglwidgets.pas --descr=nvglutwidgets.xml --input=../src/nvwidgets/nvglutwidgets.pas --descr=nvshaderutils.xml --input=../src/nvglutils/nvshaderutils.pas --format=html +fpdoc --package=nvidia-widgets --descr=nvwidgets.xml --input=../src/nvwidgets/nvWidgets.pas --descr=nvglwidgets.xml --input=../src/nvwidgets/nvglwidgets.pas --descr=nvglutwidgets.xml --input=../src/nvwidgets/nvglutwidgets.pas --descr=nvshaderutils.xml --input=../src/nvglutils/nvshaderutils.pas --descr=glfreetype.xml --input=../src/gl/glfreetype.pas --format=html diff --git a/components/nvidia-widgets/doc/images/nvwidgets.png b/components/nvidia-widgets/doc/images/nvwidgets.png index 81821d6fc..28d770aac 100644 Binary files a/components/nvidia-widgets/doc/images/nvwidgets.png and b/components/nvidia-widgets/doc/images/nvwidgets.png differ diff --git a/components/nvidia-widgets/doc/index-8.html b/components/nvidia-widgets/doc/index-8.html index 25de8713e..471ac7049 100644 --- a/components/nvidia-widgets/doc/index-8.html +++ b/components/nvidia-widgets/doc/index-8.html @@ -27,6 +27,7 @@ P  R  S  +T  U  @@ -87,60 +88,65 @@

G

- + - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + +
GLUIPainterglFreeType GroupFlags_GrowLeftFromBottomGroupFlags_LayoutNoMargin
GlutUIContextGroupFlags_GrowLeftFromTop GroupFlags_LayoutNone
GroupGroupFlags_GrowRightFromBottomGLUIPainterGroupFlags_GrowLeftFromTop GroupFlags_LayoutNoSpace
GroupFlags_AlignBottomGroupFlags_GrowRightFromTopGlutUIContextGroupFlags_GrowRightFromBottom GroupFlags_LayoutVertical
GroupFlags_AlignLeftGroupFlags_GrowUpFromLeftGroupGroupFlags_GrowRightFromTop GroupFlags_LayoutXMask
GroupFlags_AlignMaskGroupFlags_GrowUpFromRightGroupFlags_AlignBottomGroupFlags_GrowUpFromLeft GroupFlags_StartBottom
GroupFlags_AlignRightGroupFlags_LayoutDefaultGroupFlags_AlignLeftGroupFlags_GrowUpFromRight GroupFlags_StartLeft
GroupFlags_AlignTopGroupFlags_LayoutDefaultFallbackGroupFlags_AlignMaskGroupFlags_LayoutDefault GroupFlags_StartMask
GroupFlags_AlignXMaskGroupFlags_LayoutForceGroupFlags_AlignRightGroupFlags_LayoutDefaultFallback GroupFlags_StartRight
GroupFlags_GrowDownFromLeftGroupFlags_LayoutHorizontalGroupFlags_AlignTopGroupFlags_LayoutForce GroupFlags_StartTop
GroupFlags_GrowDownFromRightGroupFlags_LayoutMaskGroupFlags_AlignXMaskGroupFlags_LayoutHorizontal GroupFlags_StartXMask
GroupFlags_GrowDownFromLeftGroupFlags_LayoutMask
GroupFlags_GrowDownFromRightGroupFlags_LayoutNoMargin

K

@@ -233,6 +239,14 @@
SetRect
+

T

+ + + + + + +
TGLFreeTypeFont

U

diff --git a/components/nvidia-widgets/doc/index.html b/components/nvidia-widgets/doc/index.html index c6169dc7f..c19d92de5 100644 --- a/components/nvidia-widgets/doc/index.html +++ b/components/nvidia-widgets/doc/index.html @@ -18,6 +18,11 @@

Units

+ + + + + diff --git a/components/nvidia-widgets/doc/nvwidgets.chm b/components/nvidia-widgets/doc/nvwidgets.chm index 6f17f94bf..e69de29bb 100644 Binary files a/components/nvidia-widgets/doc/nvwidgets.chm and b/components/nvidia-widgets/doc/nvwidgets.chm differ diff --git a/components/nvidia-widgets/src/gl/glfreetype.pas b/components/nvidia-widgets/src/gl/glfreetype.pas new file mode 100644 index 000000000..de5a8d83b --- /dev/null +++ b/components/nvidia-widgets/src/gl/glfreetype.pas @@ -0,0 +1,312 @@ +(* + A quick and simple opengl font library that uses GNU freetype2, written + and distributed as part of a tutorial for nehe.gamedev.net. + Sven Olsen, 2003 +*) +unit glFreeType; + +{$mode objfpc}{$H+} + +interface + +uses + SysUtils, freetypeh, GL, GLu; + +//This holds all of the information related to any +//freetype font that we want to create. +type + TGLFreeTypeFont = object + Height: cardinal; //< Holds the height of the font. + textures: pGLuint; //< Holds the texture id's + list_base: GLuint; //< Holds the first display list id + + //The init function will create a font of + //of the height h from the file fname. + procedure Init(const fname: string; AHeight: cardinal); + + //Free all the resources assosiated with the font. + procedure Clean; + + //The flagship function of the library - this thing will print + //out text at window coordinates x, y, using the font ft_font. + //The current modelview matrix will also be applied to the text. + procedure Print(x, y: double; Text: string); + end; + +implementation + +const + CHAR_NUM = 255; + +//This function gets the first power of 2 >= the +//int that we pass it. +function next_p2(a: integer): integer; inline; +var + rval: integer; +begin + rval := 1; + while rval < a do + rval := rval shl 1; + Result := rval; +end; + +//Create a display list coresponding to the give character. +procedure make_dlist(face: PFT_Face; ch: char; list_base: GLuint; tex_base: pGLuint); +var + glyph: PFT_Glyph; + bitmap_glyph: PFT_BitmapGlyph; + bitmap: FT_Bitmap; + Width: integer; + Height: integer; + expanded_data: pGLubyte; + x: double; + y: double; + i, j: integer; +begin + //The first thing we do is get FreeType to render our character + //into a bitmap. This actually requires a couple of FreeType commands: + + //Load the Glyph for our character. + if FT_Load_Glyph(face, FT_Get_Char_Index(face, Ord(ch)), FT_LOAD_DEFAULT) = 1 then + raise Exception.Create('FT_Load_Glyph failed'); + + //Move the face's glyph into a Glyph object. + if FT_Get_Glyph(face^.glyph, glyph) = 1 then + raise Exception.Create('FT_Get_Glyph failed'); + + FT_Glyph_To_Bitmap(glyph, FT_RENDER_MODE_NORMAL, nil, True); + + //Convert the glyph to a bitmap. + bitmap_glyph := PFT_BitmapGlyph(glyph); + + //This reference will make accessing the bitmap easier + bitmap := bitmap_glyph^.bitmap; + + //Use our helper function to get the widths of + //the bitmap data that we will need in order to create + //our texture. + Width := next_p2(bitmap.Width); + Height := next_p2(bitmap.rows); + + //Allocate memory for the texture data. + GetMem(expanded_data, 2 * Width * Height); + //writeln(2 * Width * Height, 'bytes for character #', Ord(ch), ' - ', ch); + + //Here we fill in the data for the expanded bitmap. + //Notice that we are using two channel bitmap (one for + //luminocity and one for alpha), but we assign + //both luminocity and alpha to the value that we + //find in the FreeType bitmap. + //We use the ?: operator so that value which we use + //will be 0 if we are in the padding zone, and whatever + //is the the Freetype bitmap otherwise. + for j := 0 to Height - 1 do + begin + for i := 0 to Width - 1 do + begin + if (i >= bitmap.Width) or (j >= bitmap.rows) then + expanded_data[2 * (i + j * Width)] := 0 + else + expanded_data[2 * (i + j * Width)] := byte((bitmap.buffer + (i + bitmap.Width * j))^); + + //write(expanded_data[2 * (i + j * Width)]:3, ' '); + + expanded_data[2 * (i + j * Width) + 1] := expanded_data[2 * (i + j * Width)]; + end; + + //writeln; + end; + + glBindTexture(GL_TEXTURE_2D, tex_base[Ord(ch)]); + + //Now we just setup some texture paramaters. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data); + + //Here we actually create the texture itself, notice + //that we are using GL_LUMINANCE_ALPHA to indicate that + //we are using 2 channel data. + + //With the texture created, we don't need to expanded data anymore + FreeMem(expanded_data, 2 * Width * Height); + glNewList(list_base + Ord(ch), GL_COMPILE); + + //So now we can create the display list + glBindTexture(GL_TEXTURE_2D, tex_base[Ord(ch)]); + glPushMatrix; + glTranslatef(bitmap_glyph^.left, 0, 0); + + //first we need to move over a little so that + //the character has the right amount of space + //between it and the one before it. + glTranslatef(0, bitmap_glyph^.top - bitmap.rows, 0); + + //Now we move down a little in the case that the + //bitmap extends past the bottom of the line + //(this is only true for characters like 'g' or 'y'. + + //Now we need to account for the fact that many of + //our textures are filled with empty padding space. + //We figure what portion of the texture is used by + //the actual character and store that information in + //the x and y variables, then when we draw the + //quad, we will only reference the parts of the texture + //that we contain the character itself. + x := bitmap.Width / Width; + y := bitmap.rows / Height; + + //Here we draw the texturemaped quads. + //The bitmap that we got from FreeType was not + //oriented quite like we would like it to be, + //so we need to link the texture to the quad + //so that the result will be properly aligned. + glBegin(GL_QUADS); + glTexCoord2d(0, 0); + glVertex2f(0, bitmap.rows); + glTexCoord2d(0, y); + glVertex2f(0, 0); + glTexCoord2d(x, y); + glVertex2f(bitmap.Width, 0); + glTexCoord2d(x, 0); + glVertex2f(bitmap.Width, bitmap.rows); + glEnd; + + glPopMatrix; + glTranslatef(face^.glyph^.advance.x shr 6, 0, 0); + + //increment the raster position as if we were a bitmap font. + //(only needed if you want to calculate text length) + glBitmap(0, 0, 0, 0, face^.glyph^.advance.x shr 6, 0, nil); + + //Finish the display list + glEndList; +end; + +procedure TGLFreeTypeFont.Init(const fname: string; AHeight: cardinal); +var + library_: PFT_Library = nil; + face: PFT_Face = nil; //The object in which Freetype holds information on a given font is called a "face". + i: byte; +begin + //Allocate some memory to store the texture ids. + GetMem(textures, CHAR_NUM * SizeOf(GLuint)); + + Height := AHeight; + + //Create and initilize a freetype font library. + if FT_Init_FreeType(library_) = 1 then + raise Exception.Create('FT_Init_FreeType failed'); + + //This is where we load in the font information from the file. + //Of all the places where the code might die, this is the most likely, + //as FT_New_Face will die if the font file does not exist or is somehow broken. + if FT_New_Face(library_, PChar(fname), 0, face) = 1 then + raise Exception.Create('FT_New_Face failed (there is probably a problem with your font file)'); + + //For some twisted reason, Freetype measures font size + //in terms of 1/64ths of pixels. Thus, to make a font + //h pixels high, we need to request a size of h*64. + //(h << 6 is just a prettier way of writting h*64) + FT_Set_Char_Size(face, Height shl 6, Height shl 6, 96, 96); + + //Here we ask opengl to allocate resources for + //all the textures and displays lists which we + //are about to create. + list_base := glGenLists(CHAR_NUM); + glGenTextures(CHAR_NUM, textures); + + //This is where we actually create each of the fonts display lists. + for i := 0 to CHAR_NUM - 1 do + make_dlist(face, Chr(i), list_base, textures); + + //We don't need the face information now that the display + //lists have been created, so we free the assosiated resources. + FT_Done_Face(face); + + //Ditto for the library. + FT_Done_FreeType(library_); +end; + +procedure TGLFreeTypeFont.Clean; +begin + glDeleteLists(list_base, CHAR_NUM); + glDeleteTextures(CHAR_NUM, textures); + FreeMem(textures, CHAR_NUM * SizeOf(GLuint)); +end; + +//A fairly straight forward function that pushes +//a projection matrix that will make object world +//coordinates identical to window coordinates. +procedure pushScreenCoordinateMatrix; +var + viewport: array [0..3] of GLint; +begin + glPushAttrib(GL_TRANSFORM_BIT); + glGetIntegerv(GL_VIEWPORT, viewport); + glMatrixMode(GL_PROJECTION); + glPushMatrix; + glLoadIdentity; + gluOrtho2D(viewport[0], viewport[2], viewport[1], viewport[3]); + glPopAttrib; +end; + +//Pops the projection matrix without changing the current +//MatrixMode. +procedure pop_projection_matrix; +begin + glPushAttrib(GL_TRANSFORM_BIT); + glMatrixMode(GL_PROJECTION); + glPopMatrix; + glPopAttrib; +end; + +//Much like Nehe's glPrint function, but modified to work +//with freetype fonts. +procedure TGLFreeTypeFont.Print(x, y: double; Text: string); +var + font: GLuint; + modelview_matrix: array [0..15] of double; +begin + pushScreenCoordinateMatrix; + + //We want a coordinate system where things coresponding to window pixels. + font := list_base; + + //Results Are Stored In Text + glPushAttrib(GL_LIST_BIT or GL_CURRENT_BIT or GL_ENABLE_BIT or GL_TRANSFORM_BIT); + + glMatrixMode(GL_MODELVIEW); + glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glListBase(font); + + glGetFloatv(GL_MODELVIEW_MATRIX, @modelview_matrix[0]); + + glPushMatrix; + glLoadIdentity; + glTranslatef(x, y, 0); + glMultMatrixf(@modelview_matrix[0]); + glCallLists(Length(Text), GL_UNSIGNED_BYTE, PChar(Text)); + + //The commented out raster position stuff can be useful if you need to + //know the length of the text that you are creating. + //If you decide to use it make sure to also uncomment the glBitmap command + //in make_dlist. + //glRasterPos2f(0,0); + glPopMatrix; + //float rpos[4]; + //glGetFloatv(GL_CURRENT_RASTER_POSITION ,rpos); + //float len=x-rpos[0]; + + glPopAttrib; + pop_projection_matrix; +end; + +end. + diff --git a/components/nvidia-widgets/src/nvwidgets/examples/example.lpi b/components/nvidia-widgets/src/nvwidgets/examples/example.lpi index 27960bbc5..82e32c239 100644 --- a/components/nvidia-widgets/src/nvwidgets/examples/example.lpi +++ b/components/nvidia-widgets/src/nvwidgets/examples/example.lpi @@ -33,7 +33,7 @@ - + @@ -59,6 +59,11 @@ + + + + + @@ -69,7 +74,7 @@ - + diff --git a/components/nvidia-widgets/src/nvwidgets/examples/example.pp b/components/nvidia-widgets/src/nvwidgets/examples/example.pp index 4c167942f..94aa3b797 100644 --- a/components/nvidia-widgets/src/nvwidgets/examples/example.pp +++ b/components/nvidia-widgets/src/nvwidgets/examples/example.pp @@ -5,7 +5,7 @@ program example; uses Classes, SysUtils, - GLut, GL, GLu, + GLut, GL, GLu, glFreeType, nvWidgets, nvGlutWidgets; type @@ -25,10 +25,13 @@ var errorScale: double = 4; compressionRate: double = 1; texture: GLuint = 0; + let: string = 'linedit test'; + glFont: TGLFreeTypeFont; procedure closeapp; begin FreeAndNil(ui); + glFont.clean; halt(0); end; @@ -79,7 +82,12 @@ var formatIdx: integer; Text: string; textureRect: Rect; + + c: integer; begin + glColor3ub(0, $ff, 0); + glFont.Print(10, 200, 'The quick brown fox jumps over the lazy dog'); + none.Rect(0, 0); ui._begin; @@ -93,6 +101,10 @@ var ui.beginGroup(GroupFlags_GrowLeftFromTop or GroupFlags_LayoutNoMargin); ui.doCheckButton(none, 'Show difference', options[OPTION_DIFF]); + ui.beginPanel(none, 'panel', true); + ui.doCheckButton(none, 'Show difference', options[OPTION_DIFF]); + ui.endPanel; + if options[OPTION_DIFF] then ui.doHorizontalSlider(none, 1, 16, errorScale); @@ -163,6 +175,8 @@ begin glutInitDisplayMode(GLUT_DOUBLE or GLUT_DEPTH or GLUT_RGB); glutCreateWindow('UI example'); + glFont.Init('Ubuntu-R.ttf', 26); //Build the freetype font + ui := GlutUIContext.Create; if not ui.init(win_w, win_h) then diff --git a/components/nvidia-widgets/src/nvwidgets/nvWidgets.pas b/components/nvidia-widgets/src/nvwidgets/nvWidgets.pas index e6b531733..adf9aa630 100644 --- a/components/nvidia-widgets/src/nvwidgets/nvWidgets.pas +++ b/components/nvidia-widgets/src/nvwidgets/nvWidgets.pas @@ -212,7 +212,7 @@ type // UI method for processing window size events ////////////////////////////////////////////////////////////////// - procedure reshape(w: integer; h: integer); + procedure reshape(w, h: integer); // // Check if the UI is currently on Focus @@ -222,18 +222,18 @@ type // // UI method for processing mouse events ////////////////////////////////////////////////////////////////// - procedure mouse(button: integer; state: integer; modifier: integer; x: integer; y: integer); - procedure mouse(button: integer; state: integer; x: integer; y: integer); + procedure mouse(button, state, modifier, x, y: integer); + procedure mouse(button, state, x, y: integer); // // UI method for processing mouse motion events ////////////////////////////////////////////////////////////////// - procedure mouseMotion(x: integer; y: integer); + procedure mouseMotion(x, y: integer); // UI method for processing key events ////////////////////////////////////////////////////////////////// - procedure keyboard(k: byte; x: integer; y: integer); + procedure keyboard(k: byte; x, y: integer); // // UI method for entering UI processing mode @@ -497,7 +497,7 @@ begin m_focusCaretPos := -1; end; -procedure UIContext.reshape(w: integer; h: integer); +procedure UIContext.reshape(w, h: integer); begin m_window.x := 0; m_window.y := 0; @@ -510,21 +510,18 @@ begin Result := m_uiOnFocus; end; -procedure UIContext.mouse(button: integer; state: integer; modifier: integer; x: integer; y: integer); +procedure UIContext.mouse(button, state, modifier, x, y: integer); var idx: integer; begin setCursor(x, y); idx := -1; - if button = MouseButton_Left then - idx := 0 - else - if button = MouseButton_Middle then - idx := 1 - else - if button = MouseButton_Right then - idx := 2; + case button of + MouseButton_Left: idx := 0; + MouseButton_Middle: idx := 1; + MouseButton_Right: idx := 2; + end; modifier := modifier and (ButtonFlags_Alt or ButtonFlags_Shift or ButtonFlags_Ctrl); @@ -538,23 +535,21 @@ begin m_mouseButton[idx].cursor.y := m_window.h - y; end; if state = 0 then - begin m_mouseButton[idx].state := ButtonFlags_On or ButtonFlags_End or modifier; - end; end; end; -procedure UIContext.mouse(button: integer; state: integer; x: integer; y: integer); +procedure UIContext.mouse(button, state, x, y: integer); begin mouse(button, state, 0, x, y); end; -procedure UIContext.mouseMotion(x: integer; y: integer); +procedure UIContext.mouseMotion(x, y: integer); begin setCursor(x, y); end; -procedure UIContext.keyboard(k: byte; x: integer; y: integer); +procedure UIContext.keyboard(k: byte; x, y: integer); begin setCursor(x, y); m_keyBuffer[m_nbKeys] := k; @@ -1122,6 +1117,8 @@ begin parentGroup^.bounds.y := minBoundY; parentGroup^.bounds.h := maxBoundY - minBoundY; end; + + {$IFDEF DEBUG} m_painter.drawDebugRect(newGroup.bounds); {$ENDIF} end; procedure UIContext.beginFrame(groupFlags: integer; const rect: Rect; style: integer);

glFreeType

  

Free Type support for OpenGL

nvGlutWidgets

  

GLut adaptor class