diff options
author | Graeme Geldenhuys <graemeg@gmail.com> | 2014-08-20 02:11:13 +0100 |
---|---|---|
committer | Graeme Geldenhuys <graemeg@gmail.com> | 2014-08-20 02:11:13 +0100 |
commit | c8acc2c1666015daeb3038c838e5018c0ecd8903 (patch) | |
tree | 5ad2edaf0e5fb6be146491226dca4d915333d80d /src/corelib/render | |
parent | c45010b6370b50f8e6192ddb7dc3d7762c8c29f7 (diff) | |
parent | d0d8573b046e5020d05c86a970d303084de19b7d (diff) | |
download | fpGUI-c8acc2c1666015daeb3038c838e5018c0ecd8903.tar.xz |
Merge branch 'release-1.2' into master
Diffstat (limited to 'src/corelib/render')
-rw-r--r-- | src/corelib/render/software/Agg2D.pas | 66 | ||||
-rw-r--r-- | src/corelib/render/software/agg-demos/Agg2DConsole.dpr | 148 | ||||
-rw-r--r-- | src/corelib/render/software/agg_2D.pas | 24 | ||||
-rw-r--r-- | src/corelib/render/software/agg_basics.pas | 4 | ||||
-rw-r--r-- | src/corelib/render/software/agg_platform_x11.inc | 83 | ||||
-rw-r--r-- | src/corelib/render/software/agg_renderer_base.pas | 12 | ||||
-rw-r--r-- | src/corelib/render/software/fpg_fontcache.pas | 347 | ||||
-rw-r--r-- | src/corelib/render/software/platform/mac/agg_platform_support.pas | 4 |
8 files changed, 666 insertions, 22 deletions
diff --git a/src/corelib/render/software/Agg2D.pas b/src/corelib/render/software/Agg2D.pas index 50a68fb8..229294d2 100644 --- a/src/corelib/render/software/Agg2D.pas +++ b/src/corelib/render/software/Agg2D.pas @@ -400,6 +400,8 @@ type procedure ClearAll(c : TAggColor ); overload; procedure ClearAll(r ,g ,b : byte; a : byte = 255 ); overload; + procedure FillAll(c: TAggColor); overload; + procedure FillAll(r, g, b: byte; a: byte = 255); overload; // Master Rendering Properties procedure BlendMode(m : TAggBlendMode ); overload; @@ -1288,6 +1290,9 @@ begin m_pathTransform.Construct (@m_convCurve ,@m_transform ); m_strokeTransform.Construct(@m_convStroke ,@m_transform ); + m_convDash.remove_all_dashes; + m_convDash.add_dash(600, 0); {$NOTE Find a better way to prevent dash generation } + {$IFDEF AGG2D_USE_FREETYPE } m_fontEngine.Construct; {$ENDIF } @@ -1491,6 +1496,22 @@ begin end; +procedure TAgg2D.FillAll(c: TAggColor); +var + clr: aggclr; +begin + clr.Construct (c ); + m_renBase.fill(@clr ); +end; + +procedure TAgg2D.FillAll(r, g, b: byte; a: byte); +var + clr: TAggColor; +begin + clr.Construct(r, g, b, a); + FillAll(clr); +end; + { CLEARCLIPBOX } procedure TAgg2D.ClearClipBox(c : TAggColor ); var @@ -1517,14 +1538,14 @@ end; { WORLDTOSCREEN } procedure TAgg2D.WorldToScreen(x ,y : PDouble ); begin - m_transform.transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) ); + m_transform.transform(@m_transform, x, y); end; { SCREENTOWORLD } procedure TAgg2D.ScreenToWorld(x ,y : PDouble ); begin - m_transform.inverse_transform(@m_transform ,double_ptr(x ) ,double_ptr(y ) ); + m_transform.inverse_transform(@m_transform, x, y); end; @@ -2649,7 +2670,8 @@ begin m_fontEngine.hinting_(m_textHints ); if cache = AGG_VectorFontCache then - m_fontEngine.height_(height ) + {$NOTE We need to fix this. Translating from font pt to pixels is inaccurate. This is just a temp fix for now. } + m_fontEngine.height_(height * 1.3333 ) // 9pt = ~12px so that is a ratio of 1.3333 else m_fontEngine.height_(worldToScreen(height ) ); {$ENDIF} @@ -3534,18 +3556,29 @@ begin end; procedure TAgg2D.DoSetFontRes(fntres: TfpgFontResourceBase); +{$IFDEF WINDOWS} begin - {$NOTE This is only temporary until I can correctly query font names } - {$IFDEF WINDOWS} + {$IFDEF AGG2D_USE_FREETYPE } + Font('c:\WINNT\Fonts\arial.ttf', 10); + {$ENDIF } + {$IFDEF AGG2D_USE_WINFONTS} Font('Arial', 13); - {$ELSE} - {$IFDEF BSD} - Font('/usr/local/lib/X11/fonts/Liberation/LiberationSans-Regular.ttf', 13); - {$ELSE} - Font('/usr/share/fonts/truetype/ttf-liberation/LiberationSans-Regular.ttf', 13); - {$ENDIF} - {$ENDIF} + {$ENDIF } end; +{$ENDIF} +{$IFDEF UNIX} +var + s: TfpgString; + i: integer; + fnt: TFontCacheItem; + lSize: double; +begin + fnt := FontCacheItemFromFontDesc(TfpgFontResource(fntres).FontDesc, lSize); + i := gFontCache.Find(fnt); + if i > 0 then + Font(gFontCache.Items[i].FileName, lSize, fnt.IsBold, fnt.IsItalic, AGG_VectorFontCache, Deg2Rad(fnt.Angle)); +end; +{$ENDIF} procedure TAgg2D.DoSetTextColor(cl: TfpgColor); var @@ -3555,7 +3588,7 @@ begin c := fpgColorToRGB(cl); t := fpgColorToRGBTriple(c); - FillColor(t.Red, t.Green, t.Blue{, t.Alpha}); + FillColor(t.Red, t.Green, t.Blue, t.Alpha); end; procedure TAgg2D.DoSetColor(cl: TfpgColor); @@ -3566,7 +3599,7 @@ begin c := fpgColorToRGB(cl); t := fpgColorToRGBTriple(c); - LineColor(t.Red, t.Green, t.Blue{, t.Alpha}); + LineColor(t.Red, t.Green, t.Blue, t.Alpha); end; procedure TAgg2D.DoSetLineStyle(awidth: integer; astyle: TfpgLineStyle); @@ -3635,7 +3668,10 @@ end; procedure TAgg2D.DoFillTriangle(x1, y1, x2, y2, x3, y3: TfpgCoord); begin - + LineWidth(1); + FillColor(LineColor); + LineColor(LineColor); + Triangle(x1+0.5, y1+0.5, x2+0.5, y2+0.5, x3+0.5, y3+0.5); end; procedure TAgg2D.DoDrawRectangle(x, y, w, h: TfpgCoord); diff --git a/src/corelib/render/software/agg-demos/Agg2DConsole.dpr b/src/corelib/render/software/agg-demos/Agg2DConsole.dpr new file mode 100644 index 00000000..bc8badbc --- /dev/null +++ b/src/corelib/render/software/agg-demos/Agg2DConsole.dpr @@ -0,0 +1,148 @@ +{ + This is a console application demo. It uses the Agg2D object, + which has a much friendlier API, to do all the drawing. We then + save the image buffer to a JPG, using the fcl-image package, + which comes standard with the Free Pascal Compiler. + +// Paths: ..\;..\svg;..\util;expat-wrap +} +program console_aggpas_2; + +{$mode objfpc}{$H+} + +uses + sysutils, + FPimage, + FPWriteJPEG, + agg_2D, + agg_basics; + +const + ImageWidth = 800; + ImageHeight = 480; + RGBA_Width = 4; + LineCount = 30; + {$IFDEF Unix} + FontFile = '../../arial.ttf'; + {$ENDIF} + {$IFDEF Windows} + FontFile = 'Arial'; + {$ENDIF} + +type + TPainter = class(TObject) + public + procedure HandlePlug; + procedure DrawStuff(agg: Agg2D_ptr); + end; + + +procedure TPainter.HandlePlug; +var + agg: Agg2D_ptr; + buf: array of int8; + image: TFPMemoryImage; + writer: TFPWriterJPEG; + x, y: Integer; + c: TFPColor; + time, totalTime: TDateTime; + function getBufItemAsWord(aDelta: byte): Word; + var + actualY: Integer; + begin + actualY := ImageHeight - y - 1; + result := + Word(buf[x * RGBA_Width + actualY * ImageWidth * RGBA_Width + aDelta] shl 8) + or Word(128); + end; +begin + totalTime := Now; + time := Now; + SetLength(buf, ImageWidth * ImageHeight * RGBA_Width); + New(agg, Construct); + agg^.attach(@(buf[0]), ImageWidth, ImageHeight, ImageWidth * RGBA_Width); + DrawStuff(agg); + Dispose(agg, Destruct); // not necessary to keep it after rendering is finished + time := Now - time; +// Logger.Emit('Draw: time spent: ' + TimeStampToString(time)); + time := Now; + image := TFPMemoryImage.create(ImageWidth, ImageHeight); + for x := 0 to ImageWidth - 1 do + for y := 0 to ImageHeight - 1 do + begin + c.red := getBufItemAsWord(2); + c.green := getBufItemAsWord(1); + c.blue := getBufItemAsWord(0); + c.alpha := getBufItemAsWord(3); + image.Colors[x, y] := c; + end; + time := Now - time; +// WriteLn('Image copy: time spent: ' + DateTimeToString(time)); + time := Now; + writer := TFPWriterJPEG.Create; + writer.CompressionQuality := $FF div 3; // bad quality plz + writer.ProgressiveEncoding := True; + image.SaveToFile('test.jpeg', writer); + image.Free; + writer.Free; + time := Now - time; +// WriteLn('Image encode: time spent: ' + DateTimeToString(time)); + totalTime := Now - totalTime; +// WriteLn('Total time: ' + DateTimeToString(totalTime)); +end; + +procedure TPainter.DrawStuff(agg: Agg2D_ptr); +var + i: Integer; + x, y, px, py, d: Double; +begin + agg^.clearAll(0, 0, 0); + agg^.lineColor(0, 0, 0, 255); + agg^.lineWidth(3); + agg^.rectangle(0, 0, ImageWidth, ImageHeight); + agg^.font(fontfile, 16); + d := ImageWidth / LineCount; + agg^.lineColor(0, 0, 0, 100); + agg^.lineWidth(1); + for i := 1 to LineCount - 1 do + begin + x := i * d; + agg^.line(x, 0, x, ImageHeight); + end; + for i := 1 to trunc(ImageHeight / d) do + begin + y := i * d; + agg^.line(0, y, ImageWidth, y); + end; + x := 0; + y := ImageHeight / 2; + px := x; + py := y; + agg^.lineColor(255, 0, 0, 200); + agg^.fillColor(0, 0, 0, 200); + agg^.lineWidth(3); + for i := 0 to LineCount - 1 do + begin + x := x + d; + y := y + Random(Round(ImageHeight / 3)) - ImageHeight / 6; + if y < 0 then + y := ImageHeight / 6; + if y >= ImageHeight then + y := ImageHeight - ImageHeight / 6; + agg^.line(px, py, x, y); + agg^.text(x, y, char_ptr(IntToStr(i) + ' point'{' шта?'})); + px := x; + py := y; + end; +end; + + +var + p: TPainter; +begin + Randomize; + p := TPainter.Create; + p.HandlePlug; + p.Free; +end. + diff --git a/src/corelib/render/software/agg_2D.pas b/src/corelib/render/software/agg_2D.pas index a6296e2c..45d88e44 100644 --- a/src/corelib/render/software/agg_2D.pas +++ b/src/corelib/render/software/agg_2D.pas @@ -3,11 +3,11 @@ // Based on Anti-Grain Geometry // Copyright (C) 2005 Maxim Shemanarev (http://www.antigrain.com) // -// Agg2D - Version 1.0 Release Milano 3 (AggPas 2.3 RM3) +// Agg2D - Version 1.0 Release Milano 3 (AggPas 2.4 RM3) // Pascal Port By: Milan Marusinec alias Milano // milan@marusinec.sk // http://www.aggpas.org -// Copyright (c) 2007 +// Copyright (c) 2007 - 2008 // // Permission to copy, use, modify, sell and distribute this software // is granted provided this copyright notice appears in all copies. @@ -325,6 +325,8 @@ type procedure clearAll(c : Color ); overload; procedure clearAll(r ,g ,b : unsigned; a : unsigned = 255 ); overload; + procedure FillAll(c: Color); overload; + procedure FillAll(r, g, b: byte; a: byte = 255); overload; procedure clearClipBox(c : Color ); overload; procedure clearClipBox(r ,g ,b : unsigned; a : unsigned = 255 ); overload; @@ -424,7 +426,7 @@ type rxTop ,ryTop : double ); overload; procedure ellipse(cx ,cy ,rx ,ry : double ); - + procedure arc (cx ,cy ,rx ,ry ,start ,sweep : double ); procedure star(cx ,cy ,r1 ,r2 ,startAngle : double; numRays : int ); @@ -932,6 +934,22 @@ begin end; +procedure Agg2D.FillAll(c: Color); +var + clr: aggclr; +begin + clr.Construct (c ); + m_renBase.fill(@clr ); +end; + +procedure Agg2D.FillAll(r, g, b: byte; a: byte); +var + clr: Color; +begin + clr.Construct(r, g, b, a); + FillAll(clr); +end; + { CLEARCLIPBOX } procedure Agg2D.clearClipBox(c : Color ); var diff --git a/src/corelib/render/software/agg_basics.pas b/src/corelib/render/software/agg_basics.pas index cc116cfe..56eb6fba 100644 --- a/src/corelib/render/software/agg_basics.pas +++ b/src/corelib/render/software/agg_basics.pas @@ -357,8 +357,8 @@ type procedure NoP; { These implementations have changed to use FPC's Sar*() functions, so should - now support all platforms with ASM code. At a later date these functions - could be removed completely. } + now support all platforms without the need for ASM code. At a later date these + functions could be removed completely. } function shr_int8 (i ,shift : int8 ) : int8; inline; function shr_int16(i ,shift : int16 ) : int16; inline; function shr_int32(i ,shift : int ) : int; inline; diff --git a/src/corelib/render/software/agg_platform_x11.inc b/src/corelib/render/software/agg_platform_x11.inc index 331b572e..dc5556fa 100644 --- a/src/corelib/render/software/agg_platform_x11.inc +++ b/src/corelib/render/software/agg_platform_x11.inc @@ -18,6 +18,7 @@ {$ifdef uses_implementation} fpg_x11, + fpg_fontcache, {$endif} @@ -27,6 +28,88 @@ type // to get access to protected methods (seeing that FPC doesn't support Friend-classes) TImageHack = class(TfpgImage); +function FontCacheItemFromFontDesc(const desc: string; var asize: double): TFontCacheItem; +var + facename: string; + cp: integer; + c: char; + token: string; + prop, propval: string; + + function NextC: char; + begin + Inc(cp); + if cp > length(desc) then + c := #0 + else + c := desc[cp]; + Result := c; + end; + + procedure NextToken; + begin + token := ''; + while (c <> #0) and (c in [' ', 'a'..'z', 'A'..'Z', '_', '0'..'9', '.']) do + begin + token := token + c; + NextC; + end; + end; + +begin + Result := TFontCacheItem.Create(''); + + cp := 0; + NextC; + NextToken; + + facename := token; + // Add known substites + if lowercase(facename) = 'times' then + facename := 'Times New Roman' + else if lowercase(facename) = 'courier' then + facename := 'Courier New' + else if lowercase(facename) = 'monospace' then + facename := 'Courier New'; + Result.FamilyName := facename; + + if c = '-' then + begin + NextC; + NextToken; + asize := StrToIntDef(token, 0); + end; + + while c = ':' do + begin + NextC; + NextToken; + + prop := UpperCase(token); + propval := ''; + + if c = '=' then + begin + NextC; + NextToken; + propval := UpperCase(token); + end; + + if prop = 'BOLD' then + Result.IsBold := True + else if prop = 'ITALIC' then + Result.IsItalic := True + else if prop = 'ANGLE' then + Result.Angle := StrToFloatDef(propval, 0.0); +// else if prop = 'ANTIALIAS' then +// if propval = 'FALSE' then +// lf.lfQuality := NONANTIALIASED_QUALITY else +// if propval = 'DEFAULT' then +// lf.lfQuality := DEFAULT_QUALITY; + end; +end; + + procedure TAgg2D.DoPutBufferToScreen(x, y, w, h: TfpgCoord); var drawgc: Tgc; diff --git a/src/corelib/render/software/agg_renderer_base.pas b/src/corelib/render/software/agg_renderer_base.pas index 926aebd5..cc2bade4 100644 --- a/src/corelib/render/software/agg_renderer_base.pas +++ b/src/corelib/render/software/agg_renderer_base.pas @@ -79,6 +79,7 @@ type function bounding_ymax : int; virtual; procedure clear(c : aggclr_ptr ); + procedure fill(const c: aggclr_ptr); procedure copy_pixel (x ,y : int; c : aggclr_ptr ); virtual; procedure blend_pixel(x ,y : int; c : aggclr_ptr; cover : int8u ); virtual; @@ -348,6 +349,17 @@ begin end; +procedure renderer_base.fill(const c: aggclr_ptr); +var + y: unsigned; +begin + if (width > 0) and (height > 0) then + begin + for y:=0 to height - 1 do + m_ren.blend_hline(m_ren, 0, y, width, c, cover_mask); + end; +end; + { COPY_PIXEL } procedure renderer_base.copy_pixel(x, y: int; c: aggclr_ptr); begin diff --git a/src/corelib/render/software/fpg_fontcache.pas b/src/corelib/render/software/fpg_fontcache.pas new file mode 100644 index 00000000..15f65e40 --- /dev/null +++ b/src/corelib/render/software/fpg_fontcache.pas @@ -0,0 +1,347 @@ +{ + fpGUI - Free Pascal GUI Toolkit + + Copyright (C) 2006 - 2013 See the file AUTHORS.txt, included in this + distribution, for details of the copyright. + + See the file COPYING.modifiedLGPL, included in this distribution, + for details about redistributing fpGUI. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Description: + This is a homegrown font cache, or font translation system. AggPas + references font files (eg: *.ttf) directly, whereas the rest + of fpGUI doesn't. Under X11 for example, the translation of + 'Aria-12' to the actual *.ttf file will be done by the fontconfig + library. Unfortunately fontconfig doesn't have an API to give + use that *.ttf font file it resolved too. So for AggPas (or rather + the AggPas backend in fpGUI) we had to implement our own + font translation system. +} + +unit fpg_fontcache; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, contnrs, fpg_base; + +type + TFontCacheItem = class(TObject) + private + FAngle: double; + FFamilyName: TfpgString; + FFileName: TfpgString; + FFixedWidth: boolean; + FStyleFlags: Integer; + function GetIsBold: boolean; + function GetIsFixedWidth: boolean; + function GetIsItalic: boolean; + function GetIsRegular: boolean; + procedure SetIsBold(AValue: boolean); + procedure SetIsFixedWidth(AValue: boolean); + procedure SetIsItalic(AValue: boolean); + procedure SetIsRegular(AValue: boolean); + public + constructor Create(const AFilename: TfpgString); + property FileName: TfpgString read FFileName write FFileName; + property FamilyName: TfpgString read FFamilyName write FFamilyName; + property StyleFlags: Integer read FStyleFlags write FStyleFlags; + property IsFixedWidth: boolean read GetIsFixedWidth write SetIsFixedWidth; + property IsRegular: boolean read GetIsRegular write SetIsRegular; + property IsItalic: boolean read GetIsItalic write SetIsItalic; + property IsBold: boolean read GetIsBold write SetIsBold; + { following properties are used by FontCacheItemFromFontDesc() only } + property Angle: double read FAngle write FAngle; + end; + + + TFontCacheList = class(TObject) + private + FList: TObjectList; + procedure SearchForFont(const AFontPath: TfpgString); + function BuildFontCacheItem(const AFontFile: TfpgString): TFontCacheItem; + procedure SetStyleIfExists(var AText: Ansistring; var AStyleFlags: integer; const AStyleName: AnsiString; const AStyleBit: integer); + protected + function GetCount: integer; virtual; + function GetItem(AIndex: Integer): TFontCacheItem; virtual; + procedure SetItem(AIndex: Integer; AValue: TFontCacheItem); virtual; + public + constructor Create; + destructor Destroy; override; + procedure BuildFontCache; + function Add(const AObject: TFontCacheItem): integer; + procedure Clear; + property Count: integer read GetCount; + function IndexOf(const AObject: TFontCacheItem): integer; + function Find(const AFontCacheItem: TFontCacheItem): integer; + property Items[AIndex: Integer]: TFontCacheItem read GetItem write SetItem; default; + end; + + +function gFontCache: TFontCacheList; + +implementation + +uses + fpg_utils, + agg_font_freetype_lib; + +const + FPG_FONT_STYLE_REGULAR = 1 shl 0; { Regular, Plain, Book } + FPG_FONT_STYLE_ITALIC = 1 shl 1; { Itelic } + FPG_FONT_STYLE_BOLD = 1 shl 2; { Bold } + FPG_FONT_STYLE_CONDENSED = 1 shl 3; { Condensed } + FPG_FONT_STYLE_EXTRALIGHT = 1 shl 4; { ExtraLight } + FPG_FONT_STYLE_LIGHT = 1 shl 5; { Light } + FPG_FONT_STYLE_SEMIBOLD = 1 shl 6; { Semibold } + FPG_FONT_STYLE_MEDIUM = 1 shl 7; { Medium } + FPG_FONT_STYLE_BLACK = 1 shl 8; { Black } + FPG_FONT_STYLE_FIXEDWIDTH = 1 shl 9; { Fixedwidth } + +var + m_library: FT_Library_ptr; + uFontCacheList: TFontCacheList; + +function gFontCache: TFontCacheList; +begin + if not Assigned(uFontCacheList) then + begin + uFontCacheList := TFontCacheList.Create; + uFontCacheList.BuildFontCache; + end; + Result := uFontCacheList; +end; + +{ TFontCacheItem } + +function TFontCacheItem.GetIsBold: boolean; +begin + Result := (FStyleFlags and FPG_FONT_STYLE_BOLD) <> 0; +end; + +function TFontCacheItem.GetIsFixedWidth: boolean; +begin + Result := (FStyleFlags and FPG_FONT_STYLE_FIXEDWIDTH) <> 0; +end; + +function TFontCacheItem.GetIsItalic: boolean; +begin + Result := (FStyleFlags and FPG_FONT_STYLE_ITALIC) <> 0; +end; + +function TFontCacheItem.GetIsRegular: boolean; +begin + Result := (FStyleFlags and FPG_FONT_STYLE_REGULAR) <> 0; +end; + +procedure TFontCacheItem.SetIsBold(AValue: boolean); +begin + FStyleFlags := FStyleFlags or FPG_FONT_STYLE_BOLD; +end; + +procedure TFontCacheItem.SetIsFixedWidth(AValue: boolean); +begin + FStyleFlags := FStyleFlags or FPG_FONT_STYLE_FIXEDWIDTH; + FStyleFlags := FStyleFlags and (not FPG_FONT_STYLE_REGULAR); +end; + +procedure TFontCacheItem.SetIsItalic(AValue: boolean); +begin + FStyleFlags := FStyleFlags or FPG_FONT_STYLE_ITALIC; +end; + +procedure TFontCacheItem.SetIsRegular(AValue: boolean); +begin + FStyleFlags := FStyleFlags or FPG_FONT_STYLE_REGULAR; + FStyleFlags := FStyleFlags and (not FPG_FONT_STYLE_FIXEDWIDTH); +end; + +constructor TFontCacheItem.Create(const AFilename: TfpgString); +begin + inherited Create; + FFileName := AFilename; + FStyleFlags := FPG_FONT_STYLE_REGULAR; + FAngle := 0.0; +end; + +{ TFontCacheList } + +procedure TFontCacheList.SearchForFont(const AFontPath: TfpgString); +var + sr: TSearchRec; + lFont: TFontCacheItem; + s: TfpgString; +begin + // The extra 'or' includes Normal attribute files under Windows. faAnyFile doesn't return those. + // Reported to FPC as bug 9440 in Mantis. + if fpgFindFirst(AFontPath + AllFilesMask, faAnyFile or $00000080, sr) = 0 then + begin + repeat + // check if special files to skip + if (sr.Name = '.') or (sr.Name = '..') or (sr.Name = '') then + Continue; + // We got something, so lets continue + s := fpgFromOSEncoding(sr.Name); + if (sr.Attr and faDirectory) <> 0 then // found a directory + SearchForFont(fpgAppendPathDelim(AFontPath + s)) + else + begin // we have a file + if (lowercase(fpgExtractFileExt(s)) = '.ttf') or + (lowercase(fpgExtractFileExt(s)) = '.otf') then + begin + lFont := BuildFontCacheItem(AFontPath + s); + Add(lFont); + end; + end; + until fpgFindNext(sr) <> 0; + end; +end; + +function TFontCacheList.BuildFontCacheItem(const AFontFile: TfpgString): TFontCacheItem; +var + face_ptr: FT_Face_ptr; + s: Ansistring; + i: integer; + flags: integer; +begin + FT_New_Face(m_library, PChar(AFontFile), 0, face_ptr); + Result := TFontCacheItem.Create(AFontFile); + Result.FamilyName := face_ptr^.family_name; + + // extract simple styles first +// if (face_ptr^.face_flags and FT_FACE_FLAG_FIXED_WIDTH) <> 0 then +// Result.StyleFlags := FPG_FONT_STYLE_FIXEDWIDTH; // this should overwrite Regular style + + if (face_ptr^.style_flags and FT_STYLE_FLAG_ITALIC) <> 0 then + Result.StyleFlags := Result.StyleFlags or FPG_FONT_STYLE_ITALIC; + + if (face_ptr^.style_flags and FT_STYLE_FLAG_BOLD) <> 0 then + Result.StyleFlags := Result.StyleFlags or FPG_FONT_STYLE_BOLD; + + // Now to more complex styles stored in StyleName field. eg: 'Condensed Medium' + s := face_ptr^.style_name; + flags := Result.StyleFlags; + SetStyleIfExists(s, flags, 'Condensed', FPG_FONT_STYLE_CONDENSED); + SetStyleIfExists(s, flags, 'ExtraLight', FPG_FONT_STYLE_EXTRALIGHT); + SetStyleIfExists(s, flags, 'Light', FPG_FONT_STYLE_LIGHT); + SetStyleIfExists(s, flags, 'Semibold', FPG_FONT_STYLE_SEMIBOLD); + SetStyleIfExists(s, flags, 'Medium', FPG_FONT_STYLE_MEDIUM); + SetStyleIfExists(s, flags, 'Black', FPG_FONT_STYLE_BLACK); + Result.StyleFlags := flags; + + FT_Done_Face(face_ptr); +end; + +procedure TFontCacheList.SetStyleIfExists(var AText: Ansistring; var AStyleFlags: integer; + const AStyleName: AnsiString; const AStyleBit: integer); +var + i: integer; +begin + i := Pos(AStyleName, AText); + if i > 0 then + begin + AStyleFlags := AStyleFlags or AStyleBit; + Delete(AText, Length(AStyleName), i); + end; +end; + +function TFontCacheList.GetCount: integer; +begin + Result := FList.Count; +end; + +function TFontCacheList.GetItem(AIndex: Integer): TFontCacheItem; +begin + Result := TFontCacheItem(FList.Items[AIndex]); +end; + +procedure TFontCacheList.SetItem(AIndex: Integer; AValue: TFontCacheItem); +begin + FList.Items[AIndex] := AValue; +end; + +constructor TFontCacheList.Create; +begin + inherited Create; + FList := TObjectList.Create; +end; + +destructor TFontCacheList.Destroy; +begin + FList.Free; + inherited Destroy; +end; + +procedure TFontCacheList.BuildFontCache; +var + lPath: TfpgString; + lPathList: TStringList; + i: integer; +begin + try + m_library := nil; + FT_Init_FreeType(m_library); + + lPathList := TStringList.Create; + lPathList.Add('/usr/share/cups/fonts/'); + lPathList.Add('/usr/share/fonts/truetype/'); + lPathList.Add('/usr/local/lib/X11/fonts/'); + lPathList.Add(GetUserDir + '.fonts/'); + for i := 0 to lPathList.Count-1 do + begin + lPath := lPathList[i]; + SearchForFont(lPath); + end; + finally + FT_Done_FreeType(m_library); + m_library := nil; + lPathList.Free; + end; +end; + +function TFontCacheList.Add(const AObject: TFontCacheItem): integer; +begin + Result := FList.Add(AObject); +end; + +procedure TFontCacheList.Clear; +begin + FList.Clear; +end; + +function TFontCacheList.IndexOf(const AObject: TFontCacheItem): integer; +begin + Result := FList.IndexOf(AObject); +end; + +function TFontCacheList.Find(const AFontCacheItem: TFontCacheItem): integer; +var + i: integer; +begin + Result := -1; // nothing found + for i := 0 to Count-1 do + begin + if (Items[i].FamilyName = AFontCacheItem.FamilyName) and + (Items[i].StyleFlags = AFontCacheItem.StyleFlags) then + begin + Result := i; + exit; + end; + end; +end; + + +initialization + uFontCacheList := nil; + +finalization + uFontCacheList.Free; + +end. + diff --git a/src/corelib/render/software/platform/mac/agg_platform_support.pas b/src/corelib/render/software/platform/mac/agg_platform_support.pas index 608b7854..e9886b64 100644 --- a/src/corelib/render/software/platform/mac/agg_platform_support.pas +++ b/src/corelib/render/software/platform/mac/agg_platform_support.pas @@ -92,10 +92,10 @@ type // Possible formats of the rendering buffer. Initially I thought that it's // reasonable to create the buffer and the rendering functions in // accordance with the native pixel format of the system because it -// would have no overhead for pixel format conersion. +// would have no overhead for pixel format conversion. // But eventually I came to a conclusion that having a possibility to // convert pixel formats on demand is a good idea. First, it was X11 where -// there lots of different formats and visuals and it would be great to +// there are lots of different formats and visuals and it would be great to // render everything in, say, RGB-24 and display it automatically without // any additional efforts. The second reason is to have a possibility to // debug renderers for different pixel formats and colorspaces having only |