From fabfcb6003b9062f1c982b4273f921b984457101 Mon Sep 17 00:00:00 2001 From: Christian Budde Date: Fri, 6 Jun 2025 22:12:29 +0200 Subject: [PATCH] Fix glyph lookup in format 4 character map --- Source/PT_CharacterMap.pas | 50 +++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/Source/PT_CharacterMap.pas b/Source/PT_CharacterMap.pas index 77de067..9303772 100644 --- a/Source/PT_CharacterMap.pas +++ b/Source/PT_CharacterMap.pas @@ -95,7 +95,7 @@ TPascalTypeFormat4CharacterMap = class(TCustomPascalTypeCharacterMap) TPascalTypeFormat6CharacterMap = class(TCustomPascalTypeCharacterMap) private - FLanguage: Word; // Please see “Note on the language field in 'cmap' subtables“ in this document. + FLanguage: Word; // Please see “Note on the language field in 'cmap' subtables“ in this document. FFirstCode: Word; // First character code of subrange. FGlyphIdArray: array of Word; // Array of glyph index values for character codes in the range. function GetEntryCount: Word; @@ -120,7 +120,7 @@ TPascalTypeFormat6CharacterMap = class(TCustomPascalTypeCharacterMap) TPascalTypeFormat12CharacterMap = class(TCustomPascalTypeCharacterMap) private - FLanguage: Cardinal; // Please see “Note on the language field in 'cmap' subtables“ in this document. + FLanguage: Cardinal; // Please see “Note on the language field in 'cmap' subtables“ in this document. FCoverageArray: array of TCharMapSegmentedCoverageRecord; protected class function GetFormat: Word; override; @@ -298,20 +298,30 @@ procedure TPascalTypeFormat4CharacterMap.AssignTo(Dest: TPersistent); inherited; end; -function TPascalTypeFormat4CharacterMap.CharacterToGlyph(CharacterIndex: Integer): Integer; + +function TPascalTypeFormat4CharacterMap.CharacterToGlyph + (CharacterIndex: Integer): Integer; var - SegmentIndex: Integer; + SegmentIndex : Integer; + OffsetIndex : Integer; + SegCount : Integer; begin SegmentIndex := 0; - while (SegmentIndex < Length(FEndCount)) do - if (CharacterIndex <= FEndCount[SegmentIndex]) then - Break - else - Inc(SegmentIndex); + SegCount := Length(FEndCount); + + // find matching segment + while (SegmentIndex < SegCount) and + (CharacterIndex > FEndCount[SegmentIndex]) do + Inc(SegmentIndex); - if not(CharacterIndex >= FStartCount[SegmentIndex]) then + if SegmentIndex >= SegCount then + begin + Result := 0; + Exit; + end; + + if CharacterIndex < FStartCount[SegmentIndex] then begin - // missing glyph Result := 0; Exit; end; @@ -320,21 +330,23 @@ function TPascalTypeFormat4CharacterMap.CharacterToGlyph(CharacterIndex: Integer Result := (FIdDelta[SegmentIndex] + CharacterIndex) mod (1 shl 16) else begin - Result := FIdRangeOffset[SegmentIndex] + - (CharacterIndex - FStartCount[SegmentIndex]); + OffsetIndex := (FIdRangeOffset[SegmentIndex] div 2) + + (CharacterIndex - FStartCount[SegmentIndex]) - + (SegCount - SegmentIndex); - // modulo operation - Result := Result mod (1 shl 16); + if (OffsetIndex >= 0) and (OffsetIndex < Length(FGlyphIdArray)) then + Result := FGlyphIdArray[OffsetIndex] + else + Result := 0; - // check for missing character and add offset eventually - if Result = 0 then - Result := FIdDelta[SegmentIndex] mod (1 shl 16) + if Result <> 0 then + Result := (Result + FIdDelta[SegmentIndex]) mod (1 shl 16); end; Result := Result mod (1 shl 16); - end; + procedure TPascalTypeFormat4CharacterMap.LoadFromStream(Stream: TStream); var StartPos: Int64;