-
Notifications
You must be signed in to change notification settings - Fork 116
INativeCanvas
zhaoyipeng edited this page Oct 25, 2017
·
2 revisions
INativeCanvs最初由Aone提出并实现了基础功能,由我将其封装成接口,并增加一些功能。
Firemonkey的绘图接口,是封装了各个平台的一些基本接口,然后自己在内部实现了大量功能,因此能够在不同平台下保持基本的兼容性,但是图形效果差别巨大,尤其是在移动平台,有时候简直是惨不忍睹。
下面是iOS模拟器下面,使用Firemonkey Canvas和INativeCanvas的对比:
Firemonkey Canvas
INativeCanvas
对比可以看出,其中存在巨大的差别,当然真机上由于分辨率较高,差别没有那么明显。
在iOS上实现Native的FillText功能,遇到了几个坑:
首先,我想要使用NSString.drawInRect方法显示字符串,但是Firemonkey的封装,NSString居然少了一些方法,好在通过网友们的帮助,我找到了需要的声明,但是要想修改emb的源代码,添加这几个方法并不容易,我尝试了一下没有成功。
所以我把以下代码加入到了我的程序当中:
NSStringClass = interface(NSObjectClass)
['{B324D490-B58F-4BE8-A5F4-7DAD2E142A5E}']
{class} function availableStringEncodings: PNSStringEncoding; cdecl;
{class} function defaultCStringEncoding: NSStringEncoding; cdecl;
{class} function localizedNameOfStringEncoding(encoding: NSStringEncoding): Pointer; cdecl;
{class} function localizedStringWithFormat(localizedStringWithFormat: NSString): Pointer; cdecl;
{class} function pathWithComponents(components: NSArray): Pointer; cdecl;
{class} function stringWithCString(bytes: MarshaledAString): Pointer; cdecl; overload;
{class} function stringWithCString(cString: MarshaledAString; encoding: NSStringEncoding): Pointer; cdecl; overload;
// {class} function stringWithCString(bytes: MarshaledAString; length: NSUInteger): Pointer; cdecl; overload;
{class} function stringWithCharacters(characters: MarshaledString; length: NSUInteger): Pointer; cdecl;
{class} function stringWithContentsOfFile(path: NSString): Pointer; cdecl; overload;
{class} function stringWithContentsOfFile(path: NSString; encoding: NSStringEncoding; error: PPointer): Pointer; cdecl; overload;
{class} function stringWithContentsOfFile(path: NSString; usedEncoding: PNSStringEncoding; error: PPointer): Pointer; cdecl; overload;
{class} function stringWithContentsOfURL(url: NSURL): Pointer; cdecl; overload;
{class} function stringWithContentsOfURL(url: NSURL; encoding: NSStringEncoding; error: PPointer): Pointer; cdecl; overload;
{class} function stringWithContentsOfURL(url: NSURL; usedEncoding: PNSStringEncoding; error: PPointer): Pointer; cdecl; overload;
{class} function stringWithFormat(stringWithFormat: NSString): Pointer; cdecl;
{class} function stringWithString(string_: NSString): Pointer; cdecl;
{class} function stringWithUTF8String(nullTerminatedCString: MarshaledAString): Pointer; cdecl;
end;
NSString = interface(NSObject)
['{A62E83E4-AEB3-405F-8AFA-5B873D6E057F}']
function UTF8String: MarshaledAString; cdecl;
function boolValue: Boolean; cdecl;
function cString: MarshaledAString; cdecl;
function cStringLength: NSUInteger; cdecl;
function cStringUsingEncoding(encoding: NSStringEncoding): MarshaledAString; cdecl;
function canBeConvertedToEncoding(encoding: NSStringEncoding): Boolean; cdecl;
function capitalizedString: NSString; cdecl;
function caseInsensitiveCompare(string_: NSString): NSComparisonResult; cdecl;
function characterAtIndex(index: NSUInteger): unichar; cdecl;
function commonPrefixWithString(aString: NSString; options: NSStringCompareOptions): NSString; cdecl;
function compare(string_: NSString): NSComparisonResult; cdecl; overload;
function compare(string_: NSString; options: NSStringCompareOptions): NSComparisonResult; cdecl; overload;
function compare(string_: NSString; options: NSStringCompareOptions; range: NSRange): NSComparisonResult; cdecl; overload;
function compare(string_: NSString; options: NSStringCompareOptions; range: NSRange; locale: Pointer): NSComparisonResult; cdecl; overload;
function completePathIntoString(outputName: NSString; caseSensitive: Boolean; matchesIntoArray: NSArray; filterTypes: NSArray): NSUInteger; cdecl;
function componentsSeparatedByCharactersInSet(separator: NSCharacterSet): NSArray; cdecl;
function componentsSeparatedByString(separator: NSString): NSArray; cdecl;
function dataUsingEncoding(encoding: NSStringEncoding): NSData; cdecl; overload;
function dataUsingEncoding(encoding: NSStringEncoding; allowLossyConversion: Boolean): NSData; cdecl; overload;
function decomposedStringWithCanonicalMapping: NSString; cdecl;
function decomposedStringWithCompatibilityMapping: NSString; cdecl;
function description: NSString; cdecl;
function doubleValue: double; cdecl;
function fastestEncoding: NSStringEncoding; cdecl;
function fileSystemRepresentation: MarshaledAString; cdecl;
function floatValue: Single; cdecl;
function getBytes(buffer: Pointer; maxLength: NSUInteger; usedLength: NSUInteger; encoding: NSStringEncoding; options: NSStringEncodingConversionOptions; range: NSRange; remainingRange: PNSRange): Boolean; cdecl;
procedure getCString(bytes: MarshaledAString); cdecl; overload;
procedure getCString(bytes: MarshaledAString; maxLength: NSUInteger); cdecl; overload;
function getCString(buffer: MarshaledAString; maxLength: NSUInteger; encoding: NSStringEncoding): Boolean; cdecl; overload;
procedure getCString(bytes: MarshaledAString; maxLength: NSUInteger; range: NSRange; remainingRange: PNSRange); cdecl; overload;
procedure getCharacters(buffer: MarshaledString); cdecl; overload;
procedure getCharacters(buffer: MarshaledString; range: NSRange); cdecl; overload;
function getFileSystemRepresentation(cname: MarshaledAString; maxLength: NSUInteger): Boolean; cdecl;
function hasPrefix(aString: NSString): Boolean; cdecl;
function hasSuffix(aString: NSString): Boolean; cdecl;
function hash: NSUInteger; cdecl;
function init: Pointer; cdecl;
function initWithBytes(bytes: Pointer; length: NSUInteger; encoding: NSStringEncoding): Pointer; cdecl;
function initWithBytesNoCopy(bytes: Pointer; length: NSUInteger; encoding: NSStringEncoding; freeWhenDone: Boolean): Pointer; cdecl;
function initWithCString(bytes: MarshaledAString): Pointer; cdecl; overload;
function initWithCString(nullTerminatedCString: MarshaledAString; encoding: NSStringEncoding): Pointer; cdecl; overload;
// function initWithCString(bytes: PAnsiChar; length: NSUInteger): Pointer; cdecl; overload;
function initWithCStringNoCopy(bytes: MarshaledAString; length: NSUInteger; freeWhenDone: Boolean): Pointer; cdecl;
function initWithCharacters(characters: MarshaledString; length: NSUInteger): Pointer; cdecl;
function initWithCharactersNoCopy(characters: MarshaledString; length: NSUInteger; freeWhenDone: Boolean): Pointer; cdecl;
function initWithContentsOfFile(path: NSString): Pointer; cdecl; overload;
function initWithContentsOfFile(path: NSString; encoding: NSStringEncoding; error: PPointer): Pointer; cdecl; overload;
function initWithContentsOfFile(path: NSString; usedEncoding: PNSStringEncoding; error: PPointer): Pointer; cdecl; overload;
function initWithContentsOfURL(url: NSURL): Pointer; cdecl; overload;
function initWithContentsOfURL(url: NSURL; encoding: NSStringEncoding; error: PPointer): Pointer; cdecl; overload;
function initWithContentsOfURL(url: NSURL; usedEncoding: PNSStringEncoding; error: PPointer): Pointer; cdecl; overload;
function initWithData(data: NSData; encoding: NSStringEncoding): Pointer; cdecl;
function initWithFormat(initWithFormat: NSString): Pointer; cdecl; overload;
function initWithFormat(format: NSString; locale: Pointer): Pointer; cdecl; overload;
function initWithString(aString: NSString): Pointer; cdecl;
function initWithUTF8String(nullTerminatedCString: MarshaledAString): Pointer; cdecl;
function intValue: Integer; cdecl;
function integerValue: NSInteger; cdecl;
function isAbsolutePath: Boolean; cdecl;
function isEqualToString(aString: NSString): Boolean; cdecl;
function lastPathComponent: NSString; cdecl;
function length: NSUInteger; cdecl;
function lengthOfBytesUsingEncoding(enc: NSStringEncoding): NSUInteger; cdecl;
function lineRangeForRange(range: NSRange): NSRange; cdecl;
function localizedCaseInsensitiveCompare(string_: NSString): NSComparisonResult; cdecl;
function localizedCompare(string_: NSString): NSComparisonResult; cdecl;
function localizedStandardCompare(string_: NSString): NSComparisonResult; cdecl;
function longLongValue: Int64; cdecl;
function lossyCString: MarshaledAString; cdecl;
function lowercaseString: NSString; cdecl;
function maximumLengthOfBytesUsingEncoding(enc: NSStringEncoding): NSUInteger; cdecl;
function paragraphRangeForRange(range: NSRange): NSRange; cdecl;
function pathComponents: NSArray; cdecl;
function pathExtension: NSString; cdecl;
function precomposedStringWithCanonicalMapping: NSString; cdecl;
function precomposedStringWithCompatibilityMapping: NSString; cdecl;
function propertyList: Pointer; cdecl;
function propertyListFromStringsFileFormat: NSDictionary; cdecl;
function rangeOfCharacterFromSet(aSet: NSCharacterSet): NSRange; cdecl; overload;
function rangeOfCharacterFromSet(aSet: NSCharacterSet; options: NSStringCompareOptions): NSRange; cdecl; overload;
function rangeOfCharacterFromSet(aSet: NSCharacterSet; options: NSStringCompareOptions; range: NSRange): NSRange; cdecl; overload;
function rangeOfComposedCharacterSequenceAtIndex(index: NSUInteger): NSRange; cdecl;
function rangeOfComposedCharacterSequencesForRange(range: NSRange): NSRange; cdecl;
function rangeOfString(aString: NSString): NSRange; cdecl; overload;
function rangeOfString(aString: NSString; options: NSStringCompareOptions): NSRange; cdecl; overload;
function rangeOfString(aString: NSString; options: NSStringCompareOptions; range: NSRange): NSRange; cdecl; overload;
function rangeOfString(aString: NSString; options: NSStringCompareOptions; range: NSRange; locale: NSLocale): NSRange; cdecl; overload;
function smallestEncoding: NSStringEncoding; cdecl;
function stringByAbbreviatingWithTildeInPath: NSString; cdecl;
function stringByAddingPercentEscapesUsingEncoding(enc: NSStringEncoding): NSString; cdecl;
function stringByAppendingFormat(stringByAppendingFormat: NSString): NSString; cdecl;
function stringByAppendingPathComponent(str: NSString): NSString; cdecl;
function stringByAppendingPathExtension(str: NSString): NSString; cdecl;
function stringByAppendingString(aString: NSString): NSString; cdecl;
function stringByDeletingLastPathComponent: NSString; cdecl;
function stringByDeletingPathExtension: NSString; cdecl;
function stringByExpandingTildeInPath: NSString; cdecl;
function stringByFoldingWithOptions(options: NSStringCompareOptions; locale: NSLocale): NSString; cdecl;
function stringByPaddingToLength(newLength: NSUInteger; withString: NSString; startingAtIndex: NSUInteger): NSString; cdecl;
function stringByReplacingCharactersInRange(range: NSRange; withString: NSString): NSString; cdecl;
function stringByReplacingOccurrencesOfString(target: NSString; withString: NSString): NSString; cdecl; overload;
function stringByReplacingOccurrencesOfString(target: NSString; withString: NSString; options: NSStringCompareOptions; range: NSRange): NSString; cdecl; overload;
function stringByReplacingPercentEscapesUsingEncoding(enc: NSStringEncoding): NSString; cdecl;
function stringByResolvingSymlinksInPath: NSString; cdecl;
function stringByStandardizingPath: NSString; cdecl;
function stringByTrimmingCharactersInSet(set_: NSCharacterSet): NSString; cdecl;
function stringsByAppendingPaths(paths: NSArray): NSArray; cdecl;
function substringFromIndex(from: NSUInteger): NSString; cdecl;
function substringToIndex(to_: NSUInteger): NSString; cdecl;
function substringWithRange(range: NSRange): NSString; cdecl;
function uppercaseString: NSString; cdecl;
function writeToFile(path: NSString; atomically: Boolean): Boolean; cdecl; overload;
function writeToFile(path: NSString; atomically: Boolean; encoding: NSStringEncoding; error: PPointer): Boolean; cdecl; overload;
function writeToURL(url: NSURL; atomically: Boolean): Boolean; cdecl; overload;
function writeToURL(url: NSURL; atomically: Boolean; encoding: NSStringEncoding; error: PPointer): Boolean; cdecl; overload;
procedure drawInRect(aRect: NSRect; withAttributes: NSDictionary); cdecl;
procedure drawAtPoint(aPoint: NSPoint; withAttributes: NSDictionary); cdecl;
function sizeWithAttributes(attributes: NSDictionary): NSSize; cdecl;
function boundingRectWithSize(size: NSSize; options: NSStringDrawingOptions; attributes: NSDictionary): NSRect; cdecl;
end;
TNSString = class(TOCGenericImport<NSStringClass, NSString>) end;
function NSSTR(Str: string): NSString;
var
M: TMarshaller;
begin
Result := TNSString.Wrap(TNSString.OCClass.stringWithUTF8String(M.AsAnsi(Str, CP_UTF8).ToPointer));
end; 请注意,我是用了与系统相同的NSString名称,但是这其实已经是两个不同的类型了,在下面的代码,有时我必须使用强制类型转换。
其中:
procedure drawInRect(aRect: NSRect; withAttributes: NSDictionary); cdecl;
procedure drawAtPoint(aPoint: NSPoint; withAttributes: NSDictionary); cdecl;
function sizeWithAttributes(attributes: NSDictionary): NSSize; cdecl;
function boundingRectWithSize(size: NSSize; options: NSStringDrawingOptions; attributes: NSDictionary): NSRect; cdecl;这几个方法,是fmx缺少的。
procedure TIOSNativeCanvas.FillText(const ARect: TRectF; const AText: string; const WordWrap: Boolean; const AOpacity: Single; const Flags: TFillTextFlags; const ATextAlign, AVTextAlign: TTextAlign);
begin
NS := NSSTR(AText);
NS.drawInRect(tr, dic);
end;
当然,事情远远没有这么简单,今后我会继续讲解。