mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 09:59:20 +02:00
cocoa: update handling of DX array passed for UTF8, respecting UTF16 surrogate pairs. #35675
git-svn-id: trunk@61323 -
This commit is contained in:
parent
3f2cd1ae7e
commit
a9c11db3de
@ -348,12 +348,17 @@ type
|
|||||||
FTextContainer: NSTextContainer;
|
FTextContainer: NSTextContainer;
|
||||||
FText: String;
|
FText: String;
|
||||||
FFont: TCocoaFont;
|
FFont: TCocoaFont;
|
||||||
|
// surrogate pairs (for UTF16)
|
||||||
|
FSurr: array of NSRange;
|
||||||
|
FSurrCount: Integer;
|
||||||
procedure SetBackgoundColor(AValue: TColor);
|
procedure SetBackgoundColor(AValue: TColor);
|
||||||
procedure SetForegoundColor(AValue: TColor);
|
procedure SetForegoundColor(AValue: TColor);
|
||||||
procedure SetFont(AFont: TCocoaFont);
|
procedure SetFont(AFont: TCocoaFont);
|
||||||
procedure UpdateFont;
|
procedure UpdateFont;
|
||||||
procedure UpdateColor;
|
procedure UpdateColor;
|
||||||
function GetTextRange: NSRange;
|
function GetTextRange: NSRange;
|
||||||
|
|
||||||
|
procedure EvalSurrogate(s: NSString);
|
||||||
public
|
public
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -1245,6 +1250,40 @@ begin
|
|||||||
Result.length := FTextStorage.length;
|
Result.length := FTextStorage.length;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCocoaTextLayout.EvalSurrogate(s: NSString);
|
||||||
|
var
|
||||||
|
res : NSRange;
|
||||||
|
i : integer;
|
||||||
|
ln : integer;
|
||||||
|
scnt : integer;
|
||||||
|
ch : integer;
|
||||||
|
begin
|
||||||
|
FSurrCount := 0;
|
||||||
|
i := 0;
|
||||||
|
ln := s.length;
|
||||||
|
// must analyze the string to presence of surrogate pairs.
|
||||||
|
// this is required for the use
|
||||||
|
ch := 0;
|
||||||
|
while i < ln do
|
||||||
|
begin
|
||||||
|
res := s.rangeOfComposedCharacterSequenceAtIndex(i); //s.rangeOfComposedCharacterSequencesForRange(src);
|
||||||
|
inc(i, res.length);
|
||||||
|
if res.length>1 then
|
||||||
|
begin
|
||||||
|
if length(FSurr) = FSurrCount then
|
||||||
|
begin
|
||||||
|
if FSurrCount = 0 then SetLength(FSurr, 4)
|
||||||
|
else SetLength(FSurr, FSurrCount * 2)
|
||||||
|
end;
|
||||||
|
FSurr[FSurrCount] := res;
|
||||||
|
inc(fSurrCount);
|
||||||
|
end;
|
||||||
|
inc(ch);
|
||||||
|
end;
|
||||||
|
if ((FSurrCount = 0) and (length(FSurr)<>0)) or (length(FSurr) div 2>FSurrCount) then
|
||||||
|
SetLength(FSurr, FSurrCount);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCocoaTextLayout.SetForegoundColor(AValue: TColor);
|
procedure TCocoaTextLayout.SetForegoundColor(AValue: TColor);
|
||||||
begin
|
begin
|
||||||
if FForegroundColor <> AValue then
|
if FForegroundColor <> AValue then
|
||||||
@ -1324,6 +1363,7 @@ begin
|
|||||||
FText := NewText;
|
FText := NewText;
|
||||||
S := NSStringUTF8(NewText);
|
S := NSStringUTF8(NewText);
|
||||||
try
|
try
|
||||||
|
FSurrCount:=-1; // invalidating surragete pair search
|
||||||
FTextStorage.beginEditing;
|
FTextStorage.beginEditing;
|
||||||
if S <> nil then
|
if S <> nil then
|
||||||
FTextStorage.replaceCharactersInRange_withString(GetTextRange, S);
|
FTextStorage.replaceCharactersInRange_withString(GetTextRange, S);
|
||||||
@ -1368,7 +1408,8 @@ var
|
|||||||
Context: NSGraphicsContext;
|
Context: NSGraphicsContext;
|
||||||
Locations: array of NSPoint;
|
Locations: array of NSPoint;
|
||||||
Indexes: array of NSUInteger;
|
Indexes: array of NSUInteger;
|
||||||
I, Count: NSUInteger;
|
I,j, Count, ii: NSUInteger;
|
||||||
|
si: Integer;
|
||||||
transform : NSAffineTransform;
|
transform : NSAffineTransform;
|
||||||
begin
|
begin
|
||||||
Range := FLayout.glyphRangeForTextContainer(FTextContainer);
|
Range := FLayout.glyphRangeForTextContainer(FTextContainer);
|
||||||
@ -1399,19 +1440,52 @@ begin
|
|||||||
Pt.y := Y;
|
Pt.y := Y;
|
||||||
if Assigned(DX) then
|
if Assigned(DX) then
|
||||||
begin
|
begin
|
||||||
|
// DX - is provided for UTF8 characters. UTF8 doesn't have surrogate pairs
|
||||||
|
// UTF16 does. UTF16 is the base for NSTextLayout and NSString.
|
||||||
|
// Thus for any character in DX, there might be mulitple "characeters"
|
||||||
|
// in NSTextLayout. See #35675.
|
||||||
|
if FSurrCount<0 then EvalSurrogate(FTextStorage.string_);
|
||||||
|
|
||||||
Count := Range.length;
|
Count := Range.length;
|
||||||
SetLength(Locations, Count);
|
SetLength(Locations, Count);
|
||||||
SetLength(Indexes, Count);
|
SetLength(Indexes, Count);
|
||||||
Locations[0] := FLayout.locationForGlyphAtIndex(0);
|
Locations[0] := FLayout.locationForGlyphAtIndex(0);
|
||||||
Indexes[0] := 0;
|
Indexes[0] := 0;
|
||||||
for I := 1 to Count - 1 do
|
for I := 1 to Count - 1 do Indexes[I] := I;
|
||||||
|
|
||||||
|
// no surrogate pairs
|
||||||
|
I := 1;
|
||||||
|
j := 0;
|
||||||
|
if FSurrCount > 0 then
|
||||||
|
begin
|
||||||
|
si := 0;
|
||||||
|
for si:=0 to FSurrCount - 1 do
|
||||||
|
begin
|
||||||
|
for ii := i to FSurr[si].location do
|
||||||
|
begin
|
||||||
|
Locations[I] := Locations[I - 1];
|
||||||
|
Locations[I].x := Locations[I].x + DX[J];
|
||||||
|
inc(i);
|
||||||
|
inc(j);
|
||||||
|
end;
|
||||||
|
for ii := 2 to FSurr[si].length do
|
||||||
|
begin
|
||||||
|
Locations[I] := Locations[I - 1];
|
||||||
|
inc(I);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// remaining DX offsets
|
||||||
|
for I := I to Count - 1 do
|
||||||
begin
|
begin
|
||||||
Locations[I] := Locations[I - 1];
|
Locations[I] := Locations[I - 1];
|
||||||
Locations[I].x := Locations[I].x + DX[I - 1];
|
Locations[I].x := Locations[I].x + DX[J];
|
||||||
Indexes[I] := I;
|
inc(j);
|
||||||
end;
|
end;
|
||||||
FLayout.setLocations_startingGlyphIndexes_count_forGlyphRange(@Locations[0], @Indexes[0], Count, Range);
|
FLayout.setLocations_startingGlyphIndexes_count_forGlyphRange(@Locations[0], @Indexes[0], Count, Range);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if FillBackground then
|
if FillBackground then
|
||||||
FLayout.drawBackgroundForGlyphRange_atPoint(Range, Pt);
|
FLayout.drawBackgroundForGlyphRange_atPoint(Range, Pt);
|
||||||
FLayout.drawGlyphsForGlyphRange_atPoint(Range, Pt);
|
FLayout.drawGlyphsForGlyphRange_atPoint(Range, Pt);
|
||||||
|
Loading…
Reference in New Issue
Block a user