10

背景ビューNSTextFieldでレンダリングする可変テキストがあります。CALayeraは、そのCALayer上にあるテキストのテキストレンダリングのサブピクセルエイリアシングをサポートしていないため、このテキストはごみのように見えます。

少しグーグルすると、その理由が明らかになります。SPAを有効にするには、テキストを不透明な背景にレンダリングする必要があります。この場合、不透明な背景にレンダリングすることは、可能な限り避けたいものです。より良い回避策はありますか?

自分でテキストをにレンダリングするのは完全に受け入れられますがNSImage、それが役立つ場合は、確認済みのレポートを見つけることができません。

Interface Builderではまったく問題ないように見えるので、このコンピューターのどこかに秘密があり、外に出るのに苦労していることがわかります。

4

4 に答える 4

3

回避策が見つかりました。Quartzには、透明な背景の上にサブピクセルエイリアシングを使用してテキストをレンダリングできるものはないようです。ただし、オフスクリーンビットマップバッファが正しい方法で作成されていれば、テキストをオフスクリーンビットマップバッファにレンダリングできます。このバッファの背景は不透明である必要があります。

私のビューには、以前はわずかに透明なPNG背景がありました。この背景を不透明にして問題なくレンダリングすることもできましたが、このビューはフェードインおよびフェードアウトする必要があるため、CALayerでバックアップする必要がありました。これにより、テキストが適切にレンダリングされ、その後サブピクセルエイリアシングなしでレンダリングされます。 。

これが私のコードです。それは信じられないほど冗長に思えます、誰かが私がそれを削るのを手伝ってくれるなら私はそれが大好きです。と呼ばれるNSImageViewと_titleと呼ばれるNSStringがあることを前提としていますtitle

// Create the attributed string
NSMutableAttributedString *attStr = [[[NSMutableAttributedString alloc] initWithString: title] autorelease];

NSRange strRange = NSMakeRange(0, [attStr length]);
NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize: NSSmallControlSize]];

[attStr addAttribute: NSForegroundColorAttributeName value: [NSColor whiteColor] range: strRange];
[attStr addAttribute: NSFontAttributeName value: font range: strRange];

NSMutableParagraphStyle *paraStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
[paraStyle setAlignment: NSCenterTextAlignment];
[paraStyle setLineBreakMode: NSLineBreakByTruncatingMiddle];
[attStr addAttribute: NSParagraphStyleAttributeName value: paraStyle range: strRange];

// Set up the image context
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * [_title frame].size.width;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// These constants are necessary to enable sub-pixel aliasing.
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;

// Create the memory buffer to be used as the context's workspace
unsigned char *contextBuffer = malloc([_title frame].size.height * [_title frame].size.width * 4);

CGContextRef context = CGBitmapContextCreate(contextBuffer, 
                                             [_title frame].size.width, 
                                             [_title frame].size.height, 
                                             bitsPerComponent, 
                                             bytesPerRow, 
                                             colorSpace, 
                                             bitmapInfo);


[NSGraphicsContext saveGraphicsState];

[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO]];


CGContextSetFillColorWithColor(context, CGColorGetConstantColor(kCGColorBlack));
CGRect rectangle = CGRectMake(0, 0, [_title frame].size.width,[_title frame].size.height);
CGContextAddRect(context, rectangle);
CGContextFillPath(context);

CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attStr);

CGContextSetTextPosition(context, 10.0, 10.0);
CTLineDraw(line, context);
CFRelease(line);

// Create a data provider from the context buffer in memory
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, contextBuffer, bytesPerRow * [_title frame].size.height, NULL);

// Create an image from the data provider
CGImageRef imageRef = CGImageCreate ([_title frame].size.width,
                                     [_title frame].size.height,
                                     bitsPerComponent,
                                     bytesPerPixel * 8,
                                     bytesPerRow,
                                     colorSpace,
                                     bitmapInfo,
                                     dataProvider,
                                     NULL,
                                     false,
                                     kCGRenderingIntentDefault
                                     );

// Turn it into an NSImage
NSImage *newImage = [[[NSImage alloc] initWithCGImage:imageRef size: NSZeroSize] autorelease];

CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CGImageRelease(imageRef);

free(contextBuffer);

[NSGraphicsContext restoreGraphicsState];

[_title setImage: newImage];
于 2010-12-20T21:53:12.080 に答える
0

あなたの制限が何であるか、なぜあなたが絶対にレイヤーに描画しなければならないのかはよくわかりませんが、とりわけos4.1の新機能として、CoreTextデスクトップからiOSに移植されました。おそらく、その高度なタイプ設定機能を利用して、線または円弧に沿ってグリフをレンダリングし、手間のかかる作業のほとんどを実行させることができます。これは比較的低レベルのAPIですが、非常に高速です。

- (void)drawLayer:(CALayer *)theLayer
        inContext:(CGContextRef)context
{
    CFStringRef string; CTFontRef font;  // assuming these exist

    // Initialize string, font, and context
    CFStringRef keys[] = { kCTFontAttributeName };
    CFTypeRef values[] = { font };

    CFDictionaryRef attributes =
        CFDictionaryCreate(kCFAllocatorDefault, (const void**)&keys,
            (const void**)&values, sizeof(keys) / sizeof(keys[0]),
            &kCFTypeDictionaryCallBacks,
            &kCFTypeDictionaryValueCallbacks);

    CFAttributedStringRef attrString =
        CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
    CFRelease(string);
    CFRelease(attributes);

    CTLineRef line = CTLineCreateWithAttributedString(attrString);

    // Set text position and draw the line into the graphics context
    CGContextSetTextPosition(context, 10.0, 10.0);
    CTLineDraw(line, context);
    CFRelease(line);
}

他の例には、CoreTextArcCocoaおよびCoreTextTestが含まれます

于 2010-12-07T19:42:43.573 に答える
0

これがオリジナルのポスターがそれをしたくなかった方法です、しかし私が不透明な背景を持っていても大丈夫でした...

レイヤーを作成するとき:

    layer.opaque = YES;

その後、

  - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context

     [NSGraphicsContext saveGraphicsState];
      NSGraphicsContext *nscg = [NSGraphicsContext graphicsContextWithGraphicsPort:context flipped:NO];
      [NSGraphicsContext setCurrentContext:nscg];

      NSRect ourframe = self.frame;
      // white background enables antialiasing
      [[NSColor whiteColor] setFill];
      NSRect ourNSFrame = ourframe;
      ourNSFrame.origin = NSZeroPoint;
      NSRectFill(ourNSFrame);

     [sometext drawInRect:ourNSFrame withAttributes:someattrs];

     [NSGraphicsContext restoreGraphicsState];
于 2013-10-09T15:39:18.037 に答える
-1

可変文字列が入力された後のテキストのX、Y位置は何ですか?UILabelテキストのXY位置がフロートであるという事実によって引き起こされたaについても同様の問題がありました。(変数データを中央に配置しようとしていて、XY値は半分のピクセルでした)

値を切り捨てると、ぼやけたテキストが修正されました。

于 2010-12-02T18:33:37.677 に答える