This should probably be handled somehow by gdip_format_string. DrawDriverString doesn't have access to the StringFormat, and there's a good change that the native implementation really does draw tabs as squares. Also, MeasureCharacterRanges and MeasureString will have to account for tabstops.
gdip_format_string already has logic to ignore certain characters, but it needs more thought as to how we can do that and keep the offsets passed to the callback accurate, and how to eventually pass information about tabs to the callback.
If this does turn out to be a correct change for DrawDriverString (I predict that it is not), then MeasureDriverString should be updated as well.