mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-25 13:49:16 +02:00
LazReport, added hyphenation support using Theo's bindings to libhyphen library, bumped LazReport version to 0.9.9
git-svn-id: trunk@40407 -
This commit is contained in:
parent
77bfdde159
commit
5555b24635
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -2006,6 +2006,7 @@ components/lazreport/source/lr_grped.lfm svneol=native#text/plain
|
||||
components/lazreport/source/lr_grped.pas svneol=native#text/pascal
|
||||
components/lazreport/source/lr_hilit.lfm svneol=native#text/plain
|
||||
components/lazreport/source/lr_hilit.pas svneol=native#text/pascal
|
||||
components/lazreport/source/lr_hyphen.pas svneol=native#text/pascal
|
||||
components/lazreport/source/lr_iflds.lfm svneol=native#text/plain
|
||||
components/lazreport/source/lr_iflds.pas svneol=native#text/pascal
|
||||
components/lazreport/source/lr_insp.lfm svneol=native#text/plain
|
||||
|
@ -29,8 +29,8 @@ Lazarus Port: Olivier Guilbaud, Jesus Reyes A.
|
||||
<License Value="Modified LGPL
|
||||
See license.txt and license-lazreport.txt for details.
|
||||
"/>
|
||||
<Version Minor="9" Release="8"/>
|
||||
<Files Count="62">
|
||||
<Version Minor="9" Release="9"/>
|
||||
<Files Count="63">
|
||||
<Item1>
|
||||
<Filename Value="lr_about.pas"/>
|
||||
<UnitName Value="LR_About"/>
|
||||
@ -280,6 +280,10 @@ See license.txt and license-lazreport.txt for details.
|
||||
<Filename Value="lr_dbcomponent.pas"/>
|
||||
<UnitName Value="lr_dbcomponent"/>
|
||||
</Item62>
|
||||
<Item63>
|
||||
<Filename Value="lr_hyphen.pas"/>
|
||||
<UnitName Value="lr_hyphen"/>
|
||||
</Item63>
|
||||
</Files>
|
||||
<i18n>
|
||||
<EnableI18N Value="True"/>
|
||||
|
@ -13,7 +13,7 @@ uses
|
||||
LR_GEdit, LR_GrpEd, LR_IFlds, LR_Pars, LR_pgopt, LR_PGrid, LR_PrDlg,
|
||||
LR_Prntr, LR_progr, lr_propedit, LR_Register, LR_RRect, LR_Shape, LR_Utils,
|
||||
LR_Var, LR_Vared, LR_View, LR_Newrp, Barcode, LR_DBRel, LR_DBComponent,
|
||||
LazarusPackageIntf;
|
||||
lr_hyphen, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -1232,6 +1232,7 @@ procedure frRegisterTool(const MenuCaption: String; ButtonBmp: TBitmap; OnClick:
|
||||
function GetDefaultDataSet: TfrTDataSet;
|
||||
procedure SetBit(var w: Word; e: Boolean; m: Integer);
|
||||
function frGetBandName(BandType: TfrBandType): string;
|
||||
procedure frSelectHyphenDictionary(ADict: string);
|
||||
|
||||
const
|
||||
lrTemplatePath = 'LazReportTemplate/';
|
||||
@ -1334,7 +1335,7 @@ implementation
|
||||
|
||||
uses
|
||||
strutils, LR_Fmted, LR_Prntr, LR_Progr, LR_Utils, DateUtils
|
||||
{$IFDEF JPEG}, JPEG {$ENDIF};
|
||||
{$IFDEF JPEG}, JPEG {$ENDIF}, lr_hyphen;
|
||||
|
||||
type
|
||||
|
||||
@ -1379,6 +1380,7 @@ var
|
||||
Append, WasPF: Boolean;
|
||||
CompositeMode: Boolean;
|
||||
MaxTitleSize: Integer = 0;
|
||||
FHyp: THyphen = nil;
|
||||
|
||||
{$IFDEF DebugLR}
|
||||
function Bandtyp2str(typ: TfrBandType): string;
|
||||
@ -1752,6 +1754,19 @@ begin
|
||||
result := copy(result, 3, Length(result));
|
||||
end;
|
||||
|
||||
procedure frSelectHyphenDictionary(ADict: string);
|
||||
begin
|
||||
if FHyp = nil then
|
||||
FHyp := THyphen.create;
|
||||
FHyp.Dictionary:=ADict;
|
||||
try
|
||||
FHyp.BreakWord('lazreport');
|
||||
except
|
||||
on E:Exception do
|
||||
DebugLn('Error: ', e.message,'. Hyphenation support will be disabled');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CanvasTextRectJustify(const Canvas:TCanvas;
|
||||
const ARect: TRect; X1, X2, Y: integer; const Text: string;
|
||||
Trimmed: boolean);
|
||||
@ -2936,7 +2951,7 @@ var
|
||||
size, size1, maxwidth: Integer;
|
||||
b: TWordBreaks;
|
||||
WCanvas: TCanvas;
|
||||
desc: string;
|
||||
desc, aword: string;
|
||||
|
||||
procedure OutLine(const str: String);
|
||||
var
|
||||
@ -3026,7 +3041,16 @@ var
|
||||
// find word's break points using some simple hyphenator algorithm
|
||||
// TODO: implement interface so users can use their own hyphenator
|
||||
// algorithm
|
||||
b := BreakWord(UTF8Range(s, last, i - last, Desc));
|
||||
aWord := UTF8Range(s, last, i - last, Desc);
|
||||
if (FHyp<>nil) and (FHyp.Loaded) then
|
||||
begin
|
||||
try
|
||||
b := FHyp.BreakWord(UTF8Lowercase(aWord));
|
||||
except
|
||||
b := '';
|
||||
end;
|
||||
end else
|
||||
b := BreakWord(aWord);
|
||||
|
||||
// if word can be broken in many segments, find the last segment that
|
||||
// fits within maxwidth
|
||||
@ -3042,8 +3066,12 @@ var
|
||||
end;
|
||||
end;
|
||||
|
||||
// last now points to nex char to be processed
|
||||
last := cur;
|
||||
if (not WasBreak) and (FHyp<>nil) and FHyp.Loaded then
|
||||
// if hyphenator was specified and is valid don't break
|
||||
// words which hyphenator didn't break
|
||||
else
|
||||
// last now points to nex char to be processed
|
||||
last := cur;
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
266
components/lazreport/source/lr_hyphen.pas
Normal file
266
components/lazreport/source/lr_hyphen.pas
Normal file
@ -0,0 +1,266 @@
|
||||
{ A hyphenation bindings and classes unit using libhyphen hyphenator
|
||||
|
||||
Copyright (C) 2013 Theo
|
||||
|
||||
This library is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or (at your
|
||||
option) any later version with the following modification:
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to link this library with independent modules to produce an
|
||||
executable, regardless of the license terms of these independent modules,and
|
||||
to copy and distribute the resulting executable under terms of your choice,
|
||||
provided that you also meet, for each linked independent module, the terms
|
||||
and conditions of the license of that module. An independent module is a
|
||||
module which is not derived from or based on this library. If you modify
|
||||
this library, you may extend this exception to your version of the library,
|
||||
but you are not obligated to do so. If you do not wish to do so, delete this
|
||||
exception statement from your version.
|
||||
|
||||
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. See the GNU Library General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Modified for it's inclusion into LazReport by: Jesus Reyes A.
|
||||
}
|
||||
{$MODE objfpc}{$H+}
|
||||
unit lr_hyphen;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
dynlibs, Classes, SysUtils;
|
||||
|
||||
const
|
||||
MAX_NAME = 20;
|
||||
MAX_CHARS = 100;
|
||||
|
||||
type
|
||||
PHyphenTrans = ^HyphenTrans;
|
||||
HyphenTrans = record
|
||||
ch: char;
|
||||
new_state: integer;
|
||||
end;
|
||||
|
||||
PHyphenState = ^HyphenState;
|
||||
HyphenState = record
|
||||
match: PChar;
|
||||
repl: PChar;
|
||||
replindex: char;
|
||||
replcut: char;
|
||||
fallback_state: integer;
|
||||
num_trans: integer;
|
||||
trans: PHyphenTrans;
|
||||
end;
|
||||
|
||||
PHyphenDict = ^HyphenDict;
|
||||
HyphenDict = record
|
||||
lhmin: char;
|
||||
rhmin: char;
|
||||
clhmin: char;
|
||||
crhmin: char;
|
||||
num_states: integer;
|
||||
cset: array[0..MAX_NAME - 1] of char;
|
||||
utf8: integer;
|
||||
states: PHyphenState;
|
||||
nextlevel: PHyphenDict;
|
||||
end;
|
||||
|
||||
Thnj_hyphen_load = function(const fn: PChar): PHyphenDict cdecl;
|
||||
Thnj_hyphen_free = procedure(var dict: HyphenDict) cdecl;
|
||||
Thnj_hyphen_hyphenate = function(var dict: HyphenDict; const word: PChar;
|
||||
word_size: integer; hyphens: PChar): integer cdecl;
|
||||
Thnj_hyphen_hyphenate2 = function(var dict: HyphenDict; const word: PChar;
|
||||
word_size: integer; hyphens: PChar; hyphenated_word: PChar;
|
||||
var rep: PPChar; var pos: Pointer; var cut: Pointer): integer cdecl;
|
||||
|
||||
{ THyphen }
|
||||
|
||||
THyphen = class
|
||||
private
|
||||
FDictionary: string;
|
||||
Pdict: PHyphenDict;
|
||||
procedure FreeDict;
|
||||
function CheckLibrary: boolean;
|
||||
function CheckDictionary: boolean;
|
||||
function GetLoaded: boolean;
|
||||
procedure LoadDict(DictionaryPath: string);
|
||||
procedure SetDictionary(AValue: string);
|
||||
public
|
||||
constructor create;
|
||||
destructor Destroy; override;
|
||||
|
||||
function BreakWord(Word:string):string;
|
||||
|
||||
property Dictionary: string read FDictionary write SetDictionary;
|
||||
property Loaded: boolean read GetLoaded;
|
||||
end;
|
||||
|
||||
|
||||
var
|
||||
hnj_hyphen_load: Thnj_hyphen_load;
|
||||
hnj_hyphen_free: Thnj_hyphen_free;
|
||||
hnj_hyphen_hyphenate: Thnj_hyphen_hyphenate;
|
||||
hnj_hyphen_hyphenate2: Thnj_hyphen_hyphenate2;
|
||||
HypLibLoaded: boolean = False;
|
||||
HypLibHandle: THandle;
|
||||
|
||||
function LoadLibHyphen(LibraryName: string): boolean;
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
function LoadLibHyphen(libraryName: string): boolean;
|
||||
begin
|
||||
if libraryName = '' then
|
||||
{$IFDEF windows}
|
||||
libraryName := 'hyphen.dll';
|
||||
{$ENDIF}
|
||||
{$IFDEF unix}
|
||||
libraryName := 'libhyphen.so';
|
||||
{$ENDIF}
|
||||
|
||||
Result := HypLibLoaded;
|
||||
if Result then
|
||||
exit;
|
||||
|
||||
HypLibHandle := LoadLibrary(PAnsiChar(libraryName));
|
||||
if HypLibHandle <> 0 then
|
||||
begin
|
||||
Result := True;
|
||||
|
||||
hnj_hyphen_load := Thnj_hyphen_load(GetProcAddress(HypLibHandle, 'hnj_hyphen_load'));
|
||||
if not Assigned(hnj_hyphen_load) then
|
||||
Result := False;
|
||||
hnj_hyphen_free := Thnj_hyphen_free(GetProcAddress(HypLibHandle, 'hnj_hyphen_free'));
|
||||
if not Assigned(hnj_hyphen_free) then
|
||||
Result := False;
|
||||
hnj_hyphen_hyphenate := Thnj_hyphen_hyphenate(
|
||||
GetProcAddress(HypLibHandle, 'hnj_hyphen_hyphenate'));
|
||||
if not Assigned(hnj_hyphen_hyphenate) then
|
||||
Result := False;
|
||||
hnj_hyphen_hyphenate2 := Thnj_hyphen_hyphenate2(
|
||||
GetProcAddress(HypLibHandle, 'hnj_hyphen_hyphenate2'));
|
||||
if not Assigned(hnj_hyphen_hyphenate2) then
|
||||
Result := False;
|
||||
|
||||
HypLibLoaded := Result;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ THyphen }
|
||||
|
||||
procedure THyphen.FreeDict;
|
||||
begin
|
||||
if pdict <> nil then
|
||||
hnj_hyphen_free(pdict^);
|
||||
pdict := nil;
|
||||
end;
|
||||
|
||||
function THyphen.CheckLibrary: boolean;
|
||||
begin
|
||||
result := HypLibLoaded;
|
||||
if not result then begin
|
||||
// try to load the library
|
||||
LoadLibHyphen('');
|
||||
result := HypLibLoaded;
|
||||
end;
|
||||
end;
|
||||
|
||||
function THyphen.CheckDictionary: boolean;
|
||||
begin
|
||||
result := false;
|
||||
if (FDictionary='') or not FileExists(FDictionary) then
|
||||
exit;
|
||||
if PDict=nil then
|
||||
LoadDict(FDictionary);
|
||||
result := PDict<>nil;
|
||||
end;
|
||||
|
||||
function THyphen.GetLoaded: boolean;
|
||||
begin
|
||||
result := HypLibLoaded and (PDict<>nil);
|
||||
end;
|
||||
|
||||
procedure THyphen.SetDictionary(AValue: string);
|
||||
begin
|
||||
if FDictionary=AValue then
|
||||
Exit;
|
||||
FDictionary:=AValue;
|
||||
if PDict<>nil then
|
||||
FreeDict;
|
||||
end;
|
||||
|
||||
constructor THyphen.create;
|
||||
begin
|
||||
inherited create;
|
||||
end;
|
||||
|
||||
destructor THyphen.Destroy;
|
||||
begin
|
||||
FreeDict;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function THyphen.BreakWord(Word: string): string;
|
||||
var
|
||||
i, j: cardinal;
|
||||
hyphens: PChar;
|
||||
rep: PPChar;
|
||||
pos: Pointer;
|
||||
cut: Pointer;
|
||||
len: integer;
|
||||
begin
|
||||
result := '';
|
||||
|
||||
if not CheckLibrary then
|
||||
raise Exception.Create('hyphen libarary not loaded');
|
||||
|
||||
if not CheckDictionary then
|
||||
raise Exception.Create('hyphen dictionary not loaded');
|
||||
|
||||
len := Length(word);
|
||||
hyphens := StrAlloc(Len + 5);
|
||||
rep := nil;
|
||||
pos := nil;
|
||||
cut := nil;
|
||||
try
|
||||
if hnj_hyphen_hyphenate2(pdict^, PChar(word), Len, hyphens, nil,
|
||||
rep, pos, cut) = 0 then
|
||||
begin
|
||||
j := 0;
|
||||
for i := 1 to length(hyphens)-1 do
|
||||
if Odd(Ord(hyphens[i])) then begin
|
||||
result := result + chr(i+1);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
StrDispose(hyphens);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure THyphen.LoadDict(DictionaryPath: string);
|
||||
begin
|
||||
FreeDict;
|
||||
pdict := hnj_hyphen_load(PChar(DictionaryPath))
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
if (HypLibHandle <> 0) and HypLibLoaded then
|
||||
begin
|
||||
if HypLibHandle <> 0 then
|
||||
FreeLibrary(HypLibHandle);
|
||||
HypLibLoaded := False;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user