كيف تدور حول النصوص الفقيرة التي تقدم نصًا مدعومًا من قبل Calayer

StackOverflow https://stackoverflow.com/questions/4293487

سؤال

لدي بعض النص المتغير في NSTextField التي تجعل على أ CALayer عرض الخلفية. ك CALayer لا يدعم الاسم المستعار دون بكسل لتقديم النص عن أي نص فوقه ، يبدو هذا النص هراء.

يكشف القليل من googling عن أسباب ذلك ، ويجب تقديم هذا النص على خلفية غير شفافة لتمكين SPA. إن تقديم خلفية غير شفافة هو شيء أود تجنبه إذا كان ذلك ممكنًا في هذه الحالة. هل هناك حل أفضل؟

أنا قادر تمامًا على تقديم النص بنفسي إلى NSImage, ، إذا كان ذلك سيساعد ، لكن لا يمكنني العثور على أي تقارير مؤكدة تفيد بأنها ستفعل ذلك.

يبدو الأمر جيدًا تمامًا في Builder Interface ، لذا أعلم أن السر في مكان ما داخل هذا الكمبيوتر يجهد فقط للخروج.

هل كانت مفيدة؟

المحلول

وجدت الحل البديل. لا يمكن لأي شيء في الكوارتز تقديم نص مع التعرجات دون بكسل أعلى خلفية شفافة ، على ما يبدو. ومع ذلك ، يمكنك تقديم رسالة نصية إلى مخزن مخزن للنقطات خارج الشاشة ، مما يوفر أن المخزن المؤقت لقطر النقطات خارج الشاشة قد تم إنشاؤه بالطريقة الصحيحة. يجب أن تكون خلفية هذا المخزن المؤقت غير شفاف.

كان رأيي سابقًا خلفية PNG كانت شفافة قليلاً. كان بإمكاني ببساطة أن أجعل هذه الخلفية غير شفافة وأصدرت إليها دون مشكلة ، ولكن نظرًا لأن هذا الرأي يحتاج إلى التلاشي والخروج ، فإنه يجب أن يكون مدعومًا من كالايير ، وبالتالي فإن النص يصنع مرة واحدة بشكل صحيح ، ثم يتم تقديمه بعد ذلك دون الاسم المستعار .

هذا هو الكود الخاص بي. يبدو أنه مطوّل بشكل لا يصدق ، أحب ذلك إذا كان بإمكان أي شخص مساعدتي في تخفيفه. يفترض أن لديك 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];

نصائح أخرى

لست متأكدًا تمامًا من حدودك ، أو لماذا عليك الرسم على طبقة ، ولكن جديدة في OS4.1 ضمن أشياء أخرى، النص الأساسي تم نقله إلى iOS من سطح المكتب. ربما يمكنك الاستفادة من ميزات إعداد النوع المتقدمة لتقديم الرسوم الرسومية على طول الخطوط أو حتى الأقواس وجعلها تفعل معظم الرفع الثقيل لك. إنها واجهة برمجة تطبيقات منخفضة المستوى نسبيًا ، لكنها سريعة جدًا.

- (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

إليكم كيف لم يرغب الملصق الأصلي في القيام بذلك ، لكن كان من الجيد بالنسبة لي أن يكون لدي خلفية غير شفافة ...

عندما تصنع الطبقة:

    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];

ما هي مواضع X و Y للنص بمجرد أن يتم ملؤها سلسلة متغيرة؟ كان لدي مشكلة مماثلة ل UILabel الذي كان سببها حقيقة أن الموضع xy للنص كان يطفو. (كان يحاول مركز البيانات المتغيرة وكان XY Vals نصف بكسل)

لقد اقتطمت القيم وأصلح نص الضبابية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top