Skip to content

DX12.DWrite #25

@Aqdam1978

Description

@Aqdam1978

I just UPDATED DX12.DWRITE unit; some addition and some correction.
I did not touch the original file, I just created a "patch" unit.
`
unit DW_Fixes;

{$mode objfpc}{$H+}

interface

{------------------------------------------------------------------------------
//============================================================================
// THE SOLUTION: The "Last Definition Wins" Rule
//============================================================================

This unit solves the problem by using a standard Pascal compiler feature.
When multiple units in a 'uses' clause declare a type with the same name,
the compiler uses the definition from the LAST unit it reads.

By placing this unit AFTER the standard DirectX units in your component's
'uses' clause, this new, more complete interface definitions will override
the original, incomplete ones for the scope of your unit.

This is the correct, safe way to patch the headers because:
1. It does NOT modify the original Lazarus installation files.
2. It is future-proof. When you update Lazarus, your project won't break.
If a future Lazarus update includes these fixes officially, you can
simply remove this unit from your project and 'uses' clauses.

//============================================================================
// HOW TO USE THIS UNIT
//============================================================================

  1. Add this unit file (DW_Fixes.pas) to your Lazarus project.

  2. In the 'uses' clause of any unit that needs the corrected interfaces
    add 'DW_Fixes' AFTER the standard
    DirectX units.

    uses
    ...,
    DX12.DWrite, // The original unit with incomplete interfaces
    DW_Fixes; // This unit, which provides the complete versions

  3. NOTE on 'Call by var' Errors: <===
    When you call a function from an old unit (like
    FDWriteFactory.CreateTextLayout) that has a 'var' parameter of a
    type I have now patched (e.g., IDWriteTextLayout), you will get a
    compiler error. The solution, is to use a temporary variable of the
    original, fully-qualified type for the call, and then cast the result
    to the new, patched type.

    Example:
    var
    OriginalLayout: DX12.DWRITE.IDWriteTextLayout;
    PatchedLayout: DW_Fixes.IDWriteTextLayout;
    begin
    FDWriteFactory.CreateTextLayout(..., OriginalLayout);
    PatchedLayout := OriginalLayout as IDWriteTextLayout;
    end;
    ------------------------------------------------------------------------------}

uses
Windows, DX12.DWrite;

type

//============================================================================
// FIX #0: Add missing TDWRITE_LINE_SPACING_METHOD enum values
//============================================================================
TDWRITE_LINE_SPACING_METHOD = (
DWRITE_LINE_SPACING_METHOD_DEFAULT, // Value = 0
{Line spacing depends solely on the content, adjusting to accommodate
the size of fonts and inline objects.}
DWRITE_LINE_SPACING_METHOD_UNIFORM, // Value = 1
{Lines are explicitly set to uniform spacing, regardless of the size of
fonts and inline objects. This can be useful to avoid the uneven
appearance that can occur from font fallback}
DWRITE_LINE_SPACING_METHOD_PROPORTIONAL // Value = 2
{This value is available only on Windows 10 or later,
and it can be used with IDWriteTextLayout3::SetLineSpacing,
but it can't be used with IDWriteTextFormat::SetLineSpacing}
);

//============================================================================
// FIX #1: Redeclare IDWriteTextLayout
//============================================================================
IDWriteTextLayout = interface(IDWriteTextFormat)
['{53737037-6d14-410b-9bfe-0b182bb70961}']
function SetMaxWidth(maxWidth: single): HResult; stdcall;
function SetMaxHeight(maxHeight: single): HResult; stdcall;
function SetFontCollection(fontCollection: IDWriteFontCollection; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetFontFamilyName(fontFamilyName: PWideChar; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetFontWeight(fontWeight: TDWRITE_FONT_WEIGHT; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetFontStyle(fontStyle: TDWRITE_FONT_STYLE; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetFontStretch(fontStretch: TDWRITE_FONT_STRETCH; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetFontSize(fontSize: single; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetUnderline(hasUnderline: longbool; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetStrikethrough(hasStrikethrough: longbool; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetDrawingEffect(drawingEffect: IUnknown; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetInlineObject(inlineObject: IDWriteInlineObject; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetTypography(typography: IDWriteTypography; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function SetLocaleName(localeName: PWideChar; textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetMaxWidth(): single; stdcall;
function GetMaxHeight(): single; stdcall;
function GetFontCollection(currentPosition: UINT32; out fontCollection: IDWriteFontCollection; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall; overload;
function GetFontFamilyNameLength(currentPosition: UINT32; out nameLength: UINT32; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall; overload;
function GetFontFamilyName(currentPosition: UINT32; out fontFamilyName: PWideChar; nameSize: UINT32; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;overload;
function GetFontWeight(currentPosition: UINT32; out fontWeight: TDWRITE_FONT_WEIGHT; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall; overload;
function GetFontStyle(currentPosition: UINT32; out fontStyle: TDWRITE_FONT_STYLE; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;overload;
function GetFontStretch(currentPosition: UINT32; out fontStretch: TDWRITE_FONT_STRETCH; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall; overload;
function GetFontSize(currentPosition: UINT32; out fontSize: single; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;overload;
function GetUnderline(currentPosition: UINT32; out hasUnderline: longbool; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetStrikethrough(currentPosition: UINT32; out hasStrikethrough: longbool; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetDrawingEffect(currentPosition: UINT32; out drawingEffect: IUnknown; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetInlineObject(currentPosition: UINT32; out inlineObject: IDWriteInlineObject; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetTypography(currentPosition: UINT32; out typography: IDWriteTypography; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;
function GetLocaleNameLength(currentPosition: UINT32; out nameLength: UINT32; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall;overload;
function GetLocaleName(currentPosition: UINT32; out localeName: PWideChar; nameSize: UINT32; out textRange: TDWRITE_TEXT_RANGE): HResult; stdcall; overload;
function Draw(clientDrawingContext: Pointer; renderer: IDWriteTextRenderer; originX: single; originY: single): HResult; stdcall;

// CORRECTED: 'out' keyword removed from lineMetrics parameter
function GetLineMetrics(lineMetrics: PDWRITE_LINE_METRICS; maxLineCount: UINT32;
    out actualLineCount: UINT32): HResult; stdcall;

function GetMetrics(out textMetrics: TDWRITE_TEXT_METRICS): HResult; stdcall;
function GetOverhangMetrics(out overhangs: TDWRITE_OVERHANG_METRICS): HResult; stdcall;

// CORRECTED: 'out' keyword removed from clusterMetrics parameter
function GetClusterMetrics(clusterMetrics: PDWRITE_CLUSTER_METRICS; maxClusterCount: UINT32;
    out actualClusterCount: UINT32): HResult; stdcall;

function DetermineMinWidth(out minWidth: single): HResult; stdcall;
function HitTestPoint(pointX: single; pointY: single; out isTrailingHit: longbool; out isInside: longbool;
    out hitTestMetrics: TDWRITE_HIT_TEST_METRICS): HResult; stdcall;
function HitTestTextPosition(textPosition: UINT32; isTrailingHit: longbool; out pointX: single;
    out pointY: single; out hitTestMetrics: TDWRITE_HIT_TEST_METRICS): HResult; stdcall;

// CORRECTED: 'out' keyword removed from hitTestMetrics parameter
function HitTestTextRange(textPosition: UINT32; textLength: UINT32; originX: single; originY: single;
    hitTestMetrics: PDWRITE_HIT_TEST_METRICS; maxHitTestMetricsCount: UINT32; out actualHitTestMetricsCount: UINT32): HResult; stdcall;

end;

//============================================================================
// FIX #2: Redeclare IDWriteTextAnalyzer2
//============================================================================
IDWriteTextAnalyzer2 = interface(IDWriteTextAnalyzer1)
['{553A9FF3-5693-4DF7-B52B-74806F7F2EB9}']
function GetGlyphOrientationTransform(glyphOrientationAngle: TDWRITE_GLYPH_ORIENTATION_ANGLE;
isSideways: longbool; originX: single; originY: single; out transform: TDWRITE_MATRIX): HResult; stdcall; overload;

// CORRECTED: The 'out' keyword is removed from the 'tags' parameter.
function GetTypographicFeatures(fontFace: IDWriteFontFace; scriptAnalysis: TDWRITE_SCRIPT_ANALYSIS;
    localeName: PWideChar; maxTagCount: UINT32; out actualTagCount: UINT32;
    tags: PDWRITE_FONT_FEATURE_TAG): HResult; stdcall;

function CheckTypographicFeature(fontFace: IDWriteFontFace; scriptAnalysis: TDWRITE_SCRIPT_ANALYSIS;
    localeName: PWideChar; featureTag: TDWRITE_FONT_FEATURE_TAG; glyphCount: UINT32; glyphIndices: PUINT16;
    out featureApplies: PUINT8): HResult; stdcall;

end;

implementation

end.
`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions