mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-29 17:42:41 +01:00 
			
		
		
		
	LCL, implements TextRect in PostscriptCanvas, from Tim P. Launchbury, issue #23659
git-svn-id: trunk@39866 -
This commit is contained in:
		
							parent
							
								
									6438ccc4ba
								
							
						
					
					
						commit
						03fa03c235
					
				| @ -168,6 +168,7 @@ Stefan Hille | ||||
| Takeda Matsuki | ||||
| Taras Boychuk | ||||
| Theo Lustenberger | ||||
| Tim P. Launchbury | ||||
| Tobias Giesen | ||||
| Tom Lisjac | ||||
| Tomas Gregorovic | ||||
|  | ||||
| @ -34,6 +34,11 @@ | ||||
|      - Implemente few methods | ||||
| } | ||||
| 
 | ||||
| { | ||||
| 12 December 2012      | ||||
| TextRect  implemented     T. P. Launchbury  | ||||
| }  | ||||
| 
 | ||||
| {$DEFINE ASCII85} | ||||
| 
 | ||||
| unit PostScriptCanvas; | ||||
| @ -43,8 +48,8 @@ unit PostScriptCanvas; | ||||
| interface | ||||
| 
 | ||||
| uses | ||||
|   Classes, SysUtils, FileUtil, Math, Types, Graphics, Forms, GraphMath, | ||||
|   GraphType, FPImage, IntfGraphics, Printers, LCLType, LCLIntf, | ||||
|   Classes, SysUtils, strutils, FileUtil, Math, Types, Graphics, Forms, GraphMath, | ||||
|   GraphType, FPImage, IntfGraphics, Printers, LCLType, LCLIntf, LCLProc, | ||||
|   PostScriptUnicode; | ||||
|    | ||||
| Type | ||||
| @ -166,7 +171,9 @@ Type | ||||
| 
 | ||||
|     procedure TextOut(X,Y: Integer; const Text: String); override; | ||||
|     function TextExtent(const Text: string): TSize; override; | ||||
|      | ||||
|     procedure TextRect(ARect: TRect; X, Y: integer; const Text: string; | ||||
|                        const Style: TTextStyle); override; | ||||
| 
 | ||||
|     procedure Draw(X,Y: Integer; SrcGraphic: TGraphic); override; | ||||
|     procedure StretchDraw(const DestRect: TRect; SrcGraphic: TGraphic); override; | ||||
| 
 | ||||
| @ -184,8 +191,6 @@ Type | ||||
|     procedure Pie(EllipseX1,EllipseY1,EllipseX2,EllipseY2, | ||||
|                   StartX,StartY,EndX,EndY: Integer); override; | ||||
|     procedure SetPixel(X,Y: Integer; Value: TColor); override; | ||||
|     procedure TextRect(ARect: TRect; X, Y: integer; const Text: string; | ||||
|                        const Style: TTextStyle); override; | ||||
| 
 | ||||
| 
 | ||||
|   end; | ||||
| @ -2280,21 +2285,643 @@ procedure TPostScriptPrinterCanvas.TextRect(ARect: TRect; X, Y: integer; | ||||
|   const Text: string; const Style: TTextStyle); | ||||
| var | ||||
|   OldClip: TRect; | ||||
|   Options: longint; | ||||
|   ReqState: TCanvasState; | ||||
|   fRect: TRect; | ||||
|   Offset: Integer; | ||||
| 
 | ||||
|   procedure WordWrap(AText: PChar; MaxWidthInPixel: integer; | ||||
|     out Lines: PPChar; out LineCount: integer); | ||||
| 
 | ||||
|     function FindLineEnd(LineStart: integer): integer; | ||||
|     var | ||||
|       CharLen, LineStop, LineWidth, WordWidth, WordEnd, CharWidth: integer; | ||||
|     begin | ||||
|       // first search line break or text break | ||||
|       Result := LineStart; | ||||
|       while not (AText[Result] in [#0, #10, #13]) do | ||||
|         Inc(Result); | ||||
|       if Result <= LineStart + 1 then | ||||
|         exit; | ||||
|       lineStop := Result; | ||||
| 
 | ||||
|       // get current line width in pixel | ||||
|       LineWidth := TextWidth(AText); | ||||
|       if LineWidth > MaxWidthInPixel then | ||||
|       begin | ||||
|         // line too long -> add words till line size reached | ||||
|         LineWidth := 0; | ||||
|         WordEnd := LineStart; | ||||
|         WordWidth := 0; | ||||
|         repeat | ||||
|           Result := WordEnd; | ||||
|           Inc(LineWidth, WordWidth); | ||||
|           // find word start | ||||
|           while AText[WordEnd] in [' ', #9] do | ||||
|             Inc(WordEnd); | ||||
|           // find word end | ||||
|           while not (AText[WordEnd] in [#0, ' ', #9, #10, #13]) do | ||||
|             Inc(WordEnd); | ||||
|           // calculate word width | ||||
|           if wordEnd = Result then break; | ||||
|           WordWidth := TextWidth(MidStr(AText, Result, WordEnd - Result)); | ||||
|         until LineWidth + WordWidth > MaxWidthInPixel; | ||||
|         if LineWidth = 0 then | ||||
|         begin | ||||
|           // the first word is longer than the maximum width | ||||
|           // -> add chars till line size reached | ||||
|           Result := LineStart; | ||||
|           LineWidth := 0; | ||||
|           repeat | ||||
|             charLen := UTF8CharacterLength(@AText[Result]); | ||||
|             CharWidth := TextWidth(MidStr(AText, Result, charLen)); | ||||
|             Inc(LineWidth, CharWidth); | ||||
|             if LineWidth > MaxWidthInPixel then | ||||
|               break; | ||||
|             if Result >= lineStop then | ||||
|               break; | ||||
|             Inc(Result, charLen); | ||||
|           until False; | ||||
|           // at least one char | ||||
|           if Result = LineStart then | ||||
|           begin | ||||
|             charLen := UTF8CharacterLength(@AText[Result]); | ||||
|             Inc(Result, charLen); | ||||
|           end; | ||||
|         end; | ||||
|       end; | ||||
|     end; | ||||
| 
 | ||||
|     function IsEmptyText: boolean; | ||||
|     begin | ||||
|       if (AText = nil) or (AText[0] = #0) then | ||||
|       begin | ||||
|         // no text | ||||
|         GetMem(Lines, SizeOf(PChar)); | ||||
|         Lines[0] := nil; | ||||
|         LineCount := 0; | ||||
|         Result := True; | ||||
|       end | ||||
|       else | ||||
|         Result := False; | ||||
|     end; | ||||
| 
 | ||||
|   var | ||||
|     LinesList: TFPList; | ||||
|     LineStart, LineEnd, LineLen: integer; | ||||
|     ArraySize, TotalSize: integer; | ||||
|     i: integer; | ||||
|     CurLineEntry: PPChar; | ||||
|     CurLineStart: PChar; | ||||
|   begin | ||||
|     if IsEmptyText then | ||||
|     begin | ||||
|       Lines := nil; | ||||
|       LineCount := 0; | ||||
|       exit; | ||||
|     end; | ||||
|     LinesList := TFPList.Create; | ||||
|     LineStart := 0; | ||||
| 
 | ||||
|     // find all line starts and line ends | ||||
|     repeat | ||||
|       LinesList.Add({%H-}Pointer(PtrInt(LineStart))); | ||||
|       // find line end | ||||
|       LineEnd := FindLineEnd(LineStart); | ||||
|       LinesList.Add({%H-}Pointer(PtrInt(LineEnd))); | ||||
|       // find next line start | ||||
|       LineStart := LineEnd; | ||||
|       if AText[LineStart] in [#10, #13] then | ||||
|       begin | ||||
|         // skip new line chars | ||||
|         Inc(LineStart); | ||||
|         if (AText[LineStart] in [#10, #13]) and | ||||
|           (AText[LineStart] <> AText[LineStart - 1]) then | ||||
|           Inc(LineStart); | ||||
|       end | ||||
|       else if AText[LineStart] in [' ', #9] then | ||||
|       begin | ||||
|         // skip space | ||||
|         while AText[LineStart] in [' ', #9] do | ||||
|           Inc(LineStart); | ||||
|       end; | ||||
|     until AText[LineStart] = #0; | ||||
| 
 | ||||
|     // create mem block for 'Lines': array of PChar + all lines | ||||
|     LineCount := LinesList.Count shr 1; | ||||
|     ArraySize := (LineCount + 1) * SizeOf(PChar); | ||||
|     TotalSize := ArraySize; | ||||
|     i := 0; | ||||
|     while i < LinesList.Count do | ||||
|     begin | ||||
|       // add  LineEnd - LineStart + 1 for the #0 | ||||
|       LineLen :={%H-}PtrUInt(LinesList[i + 1]) -{%H-}PtrUInt(LinesList[i]) + 1; | ||||
|       Inc(TotalSize, LineLen); | ||||
|       Inc(i, 2); | ||||
|     end; | ||||
|     GetMem(Lines, TotalSize); | ||||
|     FillChar(Lines^, TotalSize, 0); | ||||
| 
 | ||||
|     // create Lines | ||||
|     CurLineEntry := Lines; | ||||
|     CurLineStart := PChar(CurLineEntry) + ArraySize; | ||||
|     i := 0; | ||||
|     while i < LinesList.Count do | ||||
|     begin | ||||
|       // set the pointer to the start of the current line | ||||
|       CurLineEntry[i shr 1] := CurLineStart; | ||||
|       // copy the line | ||||
|       LineStart := integer({%H-}PtrUInt(LinesList[i])); | ||||
|       LineEnd := integer({%H-}PtrUInt(LinesList[i + 1])); | ||||
|       LineLen := LineEnd - LineStart; | ||||
|       if LineLen > 0 then | ||||
|         Move(AText[LineStart], CurLineStart^, LineLen); | ||||
|       Inc(CurLineStart, LineLen); | ||||
|       // add #0 as line end | ||||
|       CurLineStart^ := #0; | ||||
|       Inc(CurLineStart); | ||||
|       // next line | ||||
|       Inc(i, 2); | ||||
|     end; | ||||
|     CurLineEntry[i shr 1] := nil; | ||||
| 
 | ||||
|     LinesList.Free; | ||||
|   end; | ||||
| 
 | ||||
|   function DrawText(Str: PChar; Count: integer; var Rect: TRect; | ||||
|     Flags: cardinal): integer; | ||||
|   const | ||||
|     TabString = '        '; | ||||
|   var | ||||
|     pIndex: longint; | ||||
|     AStr: string; | ||||
| 
 | ||||
|     TM: TLCLTextmetric; | ||||
|     theRect: TRect; | ||||
|     Lines: PPChar; | ||||
|     I, NumLines: longint; | ||||
| 
 | ||||
|     l: longint; | ||||
|     Pt: TPoint; | ||||
|     SavedRect: TRect; // if font orientation <> 0 | ||||
| 
 | ||||
|     function LeftOffset: longint; | ||||
|     begin | ||||
|       if (Flags and DT_RIGHT) = DT_RIGHT then | ||||
|         Result := DT_RIGHT | ||||
|       else | ||||
|       if (Flags and DT_CENTER) = DT_CENTER then | ||||
|         Result := DT_CENTER | ||||
|       else | ||||
|         Result := DT_LEFT; | ||||
|     end; | ||||
| 
 | ||||
|     function TopOffset: longint; | ||||
|     begin | ||||
|       if (Flags and DT_BOTTOM) = DT_BOTTOM then | ||||
|         Result := DT_BOTTOM | ||||
|       else | ||||
|       if (Flags and DT_VCENTER) = DT_VCENTER then | ||||
|         Result := DT_VCENTER | ||||
|       else | ||||
|         Result := DT_TOP; | ||||
|     end; | ||||
| 
 | ||||
|     function CalcRect: boolean; | ||||
|     begin | ||||
|       Result := (Flags and DT_CALCRECT) = DT_CALCRECT; | ||||
|     end; | ||||
| 
 | ||||
| 
 | ||||
|     procedure DoCalcRect; | ||||
|     var | ||||
|       AP: TSize; | ||||
|       J, MaxWidth, LineWidth: integer; | ||||
|     begin | ||||
|       theRect := Rect; | ||||
| 
 | ||||
|       MaxWidth := theRect.Right - theRect.Left; | ||||
| 
 | ||||
|       if (Flags and DT_SINGLELINE) > 0 then | ||||
|       begin | ||||
|         // ignore word and line breaks | ||||
|         AP := TextExtent(PChar(AStr)); | ||||
|         theRect.Bottom := theRect.Top + TM.Height; | ||||
|         if (Flags and DT_CALCRECT) <> 0 then | ||||
|           theRect.Right := theRect.Left + AP.cX | ||||
|         else | ||||
|         begin | ||||
|           theRect.Right := theRect.Left + Min(MaxWidth, AP.cX); | ||||
|           if (Flags and DT_VCENTER) > 0 then | ||||
|           begin | ||||
|             OffsetRect(theRect, 0, ((Rect.Bottom - Rect.Top) - | ||||
|               (theRect.Bottom - theRect.Top)) div 2); | ||||
|           end | ||||
|           else | ||||
|           if (Flags and DT_BOTTOM) > 0 then | ||||
|           begin | ||||
|             OffsetRect(theRect, 0, (Rect.Bottom - Rect.Top) - | ||||
|               (theRect.Bottom - theRect.Top)); | ||||
|           end; | ||||
|         end; | ||||
|       end | ||||
|       else | ||||
|       begin | ||||
|         // consider line breaks | ||||
|         if (Flags and DT_WORDBREAK) = 0 then | ||||
|         begin | ||||
|           // do not break at word boundaries | ||||
|           AP := TextExtent(PChar(AStr)); | ||||
|           MaxWidth := AP.cX; | ||||
|         end; | ||||
|         WordWrap(PChar(AStr), MaxWidth, Lines, NumLines); | ||||
| 
 | ||||
|         if (Flags and DT_CALCRECT) <> 0 then | ||||
|         begin | ||||
|           LineWidth := 0; | ||||
|           if (Lines <> nil) then | ||||
|           begin | ||||
|             for J := 0 to NumLines - 1 do | ||||
|             begin | ||||
|               AP := TextExtent(Lines[J]); | ||||
|               LineWidth := Max(LineWidth, AP.cX); | ||||
|             end; | ||||
|           end; | ||||
|           LineWidth := Min(MaxWidth, LineWidth); | ||||
|         end | ||||
|         else | ||||
|           LineWidth := MaxWidth; | ||||
| 
 | ||||
|         theRect.Right := theRect.Left + LineWidth; | ||||
|         theRect.Bottom := theRect.Top + NumLines * TM.Height; | ||||
|         if NumLines > 1 then | ||||
|           Inc(theRect.Bottom, ((NumLines - 1) * TM.Descender));// space between lines | ||||
|       end; | ||||
| 
 | ||||
|       if not CalcRect then | ||||
|         case LeftOffset of | ||||
|           DT_CENTER: | ||||
|           begin | ||||
|             Offset := (Rect.Right - theRect.Right) div 2; | ||||
|             OffsetRect(theRect, offset, 0); | ||||
|           end; | ||||
|           DT_RIGHT: | ||||
|           begin | ||||
|             Offset := Rect.Right - theRect.Right; | ||||
|             OffsetRect(theRect, offset, 0); | ||||
|           end; | ||||
|         end; | ||||
|     end; | ||||
| 
 | ||||
|     // if our Font.Orientation <> 0 we must recalculate X,Y offset | ||||
|     // also it works only with DT_TOP DT_LEFT. | ||||
|     procedure CalculateOffsetWithAngle(const AFontAngle: integer; | ||||
|     var TextLeft, TextTop: integer); | ||||
|     var | ||||
|       OffsX, OffsY: integer; | ||||
|       Angle: integer; | ||||
|       Size: TSize; | ||||
|       R: TRect; | ||||
|     begin | ||||
|       R := SavedRect; | ||||
|       OffsX := R.Right - R.Left; | ||||
|       OffsY := R.Bottom - R.Top; | ||||
|       Size.cX := OffsX; | ||||
|       Size.cy := OffsY; | ||||
|       Angle := AFontAngle div 10; | ||||
|       if Angle < 0 then | ||||
|         Angle := 360 + Angle; | ||||
| 
 | ||||
|       if Angle <= 90 then | ||||
|       begin | ||||
|         OffsX := 0; | ||||
|         OffsY := Trunc(Size.cx * sin(Angle * Pi / 180)); | ||||
|       end | ||||
|       else | ||||
|       if Angle <= 180 then | ||||
|       begin | ||||
|         OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180)); | ||||
|         OffsY := Trunc(Size.cx * sin(Angle * Pi / 180) + Size.cy * | ||||
|           cos((180 - Angle) * Pi / 180)); | ||||
|       end | ||||
|       else | ||||
|       if Angle <= 270 then | ||||
|       begin | ||||
|         OffsX := Trunc(Size.cx * -cos(Angle * Pi / 180) + Size.cy * | ||||
|           sin((Angle - 180) * Pi / 180)); | ||||
|         OffsY := Trunc(Size.cy * sin((270 - Angle) * Pi / 180)); | ||||
|       end | ||||
|       else | ||||
|       if Angle <= 360 then | ||||
|       begin | ||||
|         OffsX := Trunc(Size.cy * sin((360 - Angle) * Pi / 180)); | ||||
|         OffsY := 0; | ||||
|       end; | ||||
|       TextTop := OffsY; | ||||
|       TextLeft := OffsX; | ||||
|     end; | ||||
| 
 | ||||
|     function NeedOffsetCalc: boolean; | ||||
|     begin | ||||
|       Result := (Font.Orientation <> 0) and (Flags and DT_SINGLELINE <> 0) and | ||||
|         (Flags and DT_VCENTER = 0) and (Flags and DT_CENTER = 0) and | ||||
|         (Flags and DT_RIGHT = 0) and (Flags and DT_BOTTOM = 0) and | ||||
|         (Flags and DT_CALCRECT = 0) and not IsRectEmpty(SavedRect); | ||||
|     end; | ||||
| 
 | ||||
| 
 | ||||
|     procedure DrawLineRaw(theLine: PChar; LineLength, TopPos: longint); | ||||
|     var | ||||
|       Points: array[0..1] of TSize; | ||||
|       LeftPos: longint; | ||||
|     begin | ||||
|       if LeftOffset <> DT_LEFT then | ||||
|         Points[0] := TextExtent(theLine); | ||||
| 
 | ||||
|        case LeftOffset of | ||||
|         DT_LEFT: | ||||
|           LeftPos := theRect.Left; | ||||
|         DT_CENTER: | ||||
|           LeftPos := theRect.Left + (theRect.Right - theRect.Left) div | ||||
|             2 - Points[0].cX div 2; | ||||
|         DT_RIGHT: | ||||
|           LeftPos := theRect.Right - Points[0].cX; | ||||
|       end; | ||||
| 
 | ||||
|       Pt := Point(0, 0); | ||||
|       // Draw line of Text | ||||
|       if NeedOffsetCalc then | ||||
|       begin | ||||
|         Pt.X := SavedRect.Left; | ||||
|         Pt.Y := SavedRect.Top; | ||||
|          CalculateOffsetWithAngle(Font.Orientation, Pt.X, Pt.Y); | ||||
|       end; | ||||
|       TextOut(LeftPos + Pt.X, TopPos + Pt.Y, theLine); | ||||
|     end; | ||||
| 
 | ||||
|     procedure DrawLine(theLine: PChar; LineLength, TopPos: longint); | ||||
|     var | ||||
|       Points: array[0..1] of TSize; | ||||
|       //LogP: TLogPen; | ||||
|       LeftPos: longint; | ||||
|     begin | ||||
|       FillByte({%H-}Points[0], SizeOf(Points[0]) * 2, 0); | ||||
|       if LeftOffset <> DT_Left then | ||||
|         Points[0] := TextExtent(theLine); | ||||
| 
 | ||||
|       case LeftOffset of | ||||
|         DT_LEFT: | ||||
|           LeftPos := theRect.Left; | ||||
|         DT_CENTER: | ||||
|           LeftPos := theRect.Left + (theRect.Right - theRect.Left) div | ||||
|             2 - Points[0].cX div 2; | ||||
|         DT_RIGHT: | ||||
|           LeftPos := theRect.Right - Points[0].cX; | ||||
|       end; | ||||
| 
 | ||||
|       Pt := Point(0, 0); | ||||
|       if NeedOffsetCalc then | ||||
|       begin | ||||
|         Pt.X := SavedRect.Left; | ||||
|         Pt.Y := SavedRect.Top; | ||||
|         CalculateOffsetWithAngle(Font.Orientation, Pt.X, Pt.Y); | ||||
|       end; | ||||
|       // Draw line of Text | ||||
|       TextOut(LeftPos + Pt.X, TopPos + Pt.Y, theLine); | ||||
| 
 | ||||
|       // Draw Prefix | ||||
|       if (pIndex > 0) and (pIndex <= LineLength) then | ||||
|       begin | ||||
|         //LogP.lopnStyle := PS_SOLID; | ||||
|         //LogP.lopnWidth.X := 1; | ||||
|         //LogP.lopnColor := FcPenColor;   // FIXME is this required? | ||||
| 
 | ||||
|         {Get prefix line position} | ||||
|         Points[0] := TextExtent(theLine); | ||||
|         Points[0].cX := LeftPos + Points[0].cX; | ||||
|         Points[0].cY := TopPos + tm.Height - TM.Descender + 1; | ||||
| 
 | ||||
|         Points[0] := TextExtent(aStr[pIndex]); | ||||
|         Points[1].cX := Points[0].cX + Points[1].cX; | ||||
|         Points[1].cY := Points[0].cY; | ||||
| 
 | ||||
|         {Draw prefix line} | ||||
|         Polyline(PPoint(@Points[0]), 2); | ||||
|       end; | ||||
|     end; | ||||
| 
 | ||||
|   begin | ||||
|     if (Str = nil) or (Str[0] = #0) then | ||||
|       Exit(0); | ||||
| 
 | ||||
|     if (Count < -1) or (IsRectEmpty(Rect) and | ||||
|       ((Flags and DT_CALCRECT = 0) and (Flags and DT_NOCLIP = 0))) then | ||||
|       Exit(0); | ||||
| 
 | ||||
|     // Don't try to use StrLen(Str) in cases count >= 0 | ||||
|     // In those cases str is NOT required to have a null terminator ! | ||||
|     if Count = -1 then | ||||
|       Count := StrLen(Str); | ||||
| 
 | ||||
|     Lines := nil; | ||||
|     NumLines := 0; | ||||
| 
 | ||||
|     try | ||||
|       if (Flags and (DT_SINGLELINE or DT_CALCRECT or DT_NOPREFIX or | ||||
|         DT_NOCLIP or DT_EXPANDTABS)) = (DT_SINGLELINE or DT_NOPREFIX or | ||||
|         DT_NOCLIP) then | ||||
|       begin | ||||
|         LCLIntf.CopyRect(theRect,  Rect); | ||||
|         SavedRect := Rect; | ||||
|         DrawLineRaw(Str, Count, Rect.Top); | ||||
|         Result := Rect.Bottom - Rect.Top; | ||||
|         Exit; | ||||
|       end; | ||||
| 
 | ||||
|       SetLength(AStr, Count); | ||||
|       if Count > 0 then | ||||
|         System.Move(Str^, AStr[1], Count); | ||||
| 
 | ||||
|       if (Flags and DT_EXPANDTABS) <> 0 then | ||||
|         AStr := StringReplace(AStr, #9, TabString, [rfReplaceAll]); | ||||
| 
 | ||||
| 
 | ||||
|       if (Flags and DT_NOPREFIX) <> DT_NOPREFIX then | ||||
|       begin | ||||
|         pIndex := DeleteAmpersands(AStr); | ||||
|         if pIndex > Length(AStr) then | ||||
|           pIndex := -1; // String ended in '&', which was deleted | ||||
|       end | ||||
|       else | ||||
|         pIndex := -1; | ||||
| 
 | ||||
| 
 | ||||
|       GetTextMetrics(TM{%H-}); | ||||
|       DoCalcRect; | ||||
|       Result := theRect.Bottom - theRect.Top; | ||||
|       if (Flags and DT_CALCRECT) = DT_CALCRECT then | ||||
|       begin | ||||
|         LCLIntf.CopyRect(Rect, theRect); | ||||
|         exit; | ||||
|       end; | ||||
| 
 | ||||
|       if (Flags and DT_NOCLIP) <> DT_NOCLIP then | ||||
|       begin | ||||
|         if theRect.Right > Rect.Right then | ||||
|           theRect.Right := Rect.Right; | ||||
|         if theRect.Bottom > Rect.Bottom then | ||||
|           theRect.Bottom := Rect.Bottom; | ||||
| // FIXME  I don't know what to do here | ||||
| //          IntersectClipRect( theRect.Left, theRect.Top, | ||||
| //          theRect.Right, theRect.Bottom); | ||||
|       end; | ||||
| 
 | ||||
|       if (Flags and DT_SINGLELINE) = DT_SINGLELINE then | ||||
|       begin | ||||
|         SavedRect := TheRect; | ||||
|         DrawLine(PChar(AStr), length(AStr), theRect.Top); | ||||
|         Exit; | ||||
|       end; | ||||
| 
 | ||||
|       // multiple lines | ||||
|       if Lines = nil then | ||||
|         Exit;  // nothing to do | ||||
|       if NumLines = 0 then | ||||
|         Exit; | ||||
| 
 | ||||
|       SavedRect := Classes.Rect(0, 0, 0, 0); | ||||
|       // no font orientation change if multilined text | ||||
|       for i := 0 to NumLines - 1 do | ||||
|       begin | ||||
|         if theRect.Top > theRect.Bottom then | ||||
|           Break; | ||||
| 
 | ||||
|         if ((Flags and DT_EDITCONTROL) = DT_EDITCONTROL) and | ||||
|           (tm.Height > (theRect.Bottom - theRect.Top)) then | ||||
|           Break; | ||||
| 
 | ||||
|         if Lines[i] <> nil then | ||||
|         begin | ||||
|           l := StrLen(Lines[i]); | ||||
|           DrawLine(Lines[i], l, theRect.Top); | ||||
|           Dec(pIndex, l + length(LineEnding)); | ||||
|         end; | ||||
|         Inc(theRect.Top, (TM.Descender + TM.Height));// space between lines | ||||
|       end; | ||||
| 
 | ||||
|     finally | ||||
|       Reallocmem(Lines, 0); | ||||
|     end; | ||||
|   end; | ||||
| 
 | ||||
| begin | ||||
|   {$IFDEF VerboseLCLTodos}{$WARNING TPostScriptPrinterCanvas.TextRect is not yet fully implemented!}{$ENDIF} | ||||
|   //TODO: layout, etc. | ||||
|   Changing; | ||||
| 
 | ||||
|   Options := 0; | ||||
|   case Style.Alignment of | ||||
|     taRightJustify: | ||||
|       Options := DT_RIGHT; | ||||
|     taCenter: | ||||
|       Options := DT_CENTER; | ||||
|   end; | ||||
|   case Style.Layout of | ||||
|     tlCenter: | ||||
|       Options := Options or DT_VCENTER; | ||||
|     tlBottom: | ||||
|       Options := Options or DT_BOTTOM; | ||||
|   end; | ||||
|   if Style.EndEllipsis then | ||||
|     Options := Options or DT_END_ELLIPSIS; | ||||
|   if Style.WordBreak then | ||||
|   begin | ||||
|     Options := Options or DT_WORDBREAK; | ||||
|     if Style.EndEllipsis then | ||||
|       Options := Options and not DT_END_ELLIPSIS; | ||||
|   end; | ||||
| 
 | ||||
|   if Style.SingleLine then | ||||
|     Options := Options or DT_SINGLELINE; | ||||
| 
 | ||||
|   if not Style.Clipping then | ||||
|     Options := Options or DT_NOCLIP; | ||||
| 
 | ||||
|   if Style.ExpandTabs then | ||||
|     Options := Options or DT_EXPANDTABS; | ||||
| 
 | ||||
|   if not Style.ShowPrefix then | ||||
|     Options := Options or DT_NOPREFIX; | ||||
| 
 | ||||
|   if Style.RightToLeft then | ||||
|     Options := Options or DT_RTLREADING; | ||||
| 
 | ||||
|   ReqState := [csHandleValid]; | ||||
|   if not Style.SystemFont then | ||||
|     Include(ReqState, csFontValid); | ||||
|   if Style.Opaque then | ||||
|     Include(ReqState, csBrushValid); | ||||
| 
 | ||||
|   // calculate text rectangle | ||||
|   fRect := ARect; | ||||
|   if Style.Alignment = taLeftJustify then | ||||
|     fRect.Left := X; | ||||
|   if Style.Layout = tlTop then | ||||
|     fRect.Top := Y; | ||||
| 
 | ||||
|   if (Style.Alignment in [taRightJustify, taCenter]) or | ||||
|     (Style.Layout in [tlCenter, tlBottom]) then | ||||
|   begin | ||||
|     DrawText( pChar(Text), Length(Text), fRect, DT_CALCRECT or Options); | ||||
|     case Style.Alignment of | ||||
|       taRightJustify: | ||||
|       begin | ||||
|         Offset := ARect.Right - fRect.Right; | ||||
|         LCLIntf.OffsetRect(fRect, Offset, 0); | ||||
|       end; | ||||
|       taCenter: | ||||
|       begin | ||||
|         Offset :=  (ARect.Right - fRect.Right) div 2; | ||||
|         LCLIntf.OffsetRect(fRect, offset, 0); | ||||
|       end; | ||||
|     end; | ||||
|     case Style.Layout of | ||||
|       tlCenter: | ||||
|       begin | ||||
|         Offset :=  ((ARect.Bottom - ARect.Top) - (fRect.Bottom - fRect.Top)) div 2; | ||||
|         LCLIntf.OffsetRect(fRect, 0, offset); | ||||
|       end; | ||||
|       tlBottom: | ||||
|       begin | ||||
|         Offset :=  ARect.Bottom - fRect.Bottom; | ||||
|         LCLIntf.OffsetRect(fRect, 0, offset); | ||||
|       end; | ||||
|     end; | ||||
|   end; | ||||
| 
 | ||||
|   if Style.Clipping then begin | ||||
|     OldClip := GetClipRect; | ||||
|     SetClipRect(ARect); | ||||
|     Options := Options or DT_NOCLIP; // no clipping as we are handling it here | ||||
|   end; | ||||
| 
 | ||||
|   TextOut(X,Y, Text); | ||||
|   if Style.Opaque then | ||||
|   begin | ||||
|     FillRect(fRect) | ||||
|   end; | ||||
| 
 | ||||
|   if Style.SystemFont then | ||||
|     UpdateFont(); | ||||
| 
 | ||||
|   DrawText(PChar(Text), Length(Text), fRect, Options); | ||||
| 
 | ||||
|   if Style.Clipping then | ||||
|     SetClipRect(OldClip); | ||||
| 
 | ||||
|   Changed; | ||||
| 
 | ||||
| end; | ||||
| 
 | ||||
| 
 | ||||
| function IsMaxClip(ARect:TRect):boolean; | ||||
| begin | ||||
|   Result:=(Arect.Right=MaxInt) and (ARect.Bottom=MaxInt) and (Arect.Left=0) and (ARect.Top=0); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 jesus
						jesus