示例#1
0
void quartz_draw_layout(void *layout, CGContextRef context, CGPoint position)
{
	CGContextSetTextPosition(context, position.x, position.y);
	
	CFArrayRef runs = CTLineGetGlyphRuns((CTLineRef)layout);
	CFIndex run_count = CFArrayGetCount(runs);
	CFIndex run_index;
	for (run_index = 0; run_index < run_count; ++run_index)
	{
		CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, run_index);
		CTFontRef run_font = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
		CGFontRef glyph_font = CTFontCopyGraphicsFont(run_font, NULL);
		CFIndex glyph_count = CTRunGetGlyphCount(run);
		CGGlyph glyphs[glyph_count];
		CGPoint positions[glyph_count];
		CFRange everything = CFRangeMake(0, 0);
		CTRunGetGlyphs(run, everything, glyphs);
		CTRunGetPositions(run, everything, positions);
		
		CGContextSetFont(context, glyph_font);
		CGContextSetFontSize(context, CTFontGetSize(run_font));
		CGContextShowGlyphsAtPositions(context, glyphs, positions, glyph_count);
		
		CGFontRelease(glyph_font);
	}
}
示例#2
0
文件: gammatext.cpp 项目: UIKit0/skia
static CGFontRef typefaceToCGFont(const SkTypeface* face) {
    if (NULL == face) {
        return 0;
    }

    CTFontRef ct = SkTypeface_GetCTFontRef(face);
    return CTFontCopyGraphicsFont(ct, NULL);
}
示例#3
0
CGFontRef FontPlatformData::cgFont() const
{
    CGFontRef cgFont = 0;
#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT
    cgFont = CTFontCopyGraphicsFont((CTFontRef)m_font->font()->OSXGetCTFont(), 0);
#else
    ATSFontRef fontRef;
    
    fontRef = FMGetATSFontRefFromFont(m_atsuFontID);
    
    if (fontRef)
        cgFont = CGFontCreateWithPlatformFont((void*)&fontRef);
#endif
    return cgFont;
}
static cairo_font_face_t *
pango_cairo_core_text_font_create_font_face (PangoCairoFont *font)
{
  PangoCoreTextFont *ctfont = (PangoCoreTextFont *) (font);
  CTFontRef font_id;
  CGFontRef cgfont;
  cairo_font_face_t *cairo_face;

  font_id = pango_core_text_font_get_ctfont (ctfont);
  cgfont = CTFontCopyGraphicsFont (font_id, NULL);

  cairo_face = cairo_quartz_font_face_create_for_cgfont (cgfont);

  CFRelease (cgfont);

  return cairo_face;
}
示例#5
0
文件: sdlmain.c 项目: j4y4r/j4ymame
bool sdl_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
   UniChar uni_char;
   CGGlyph glyph;
   CTFontRef ct_font = (CTFontRef)font;
   const CFIndex count = 1;
   CGRect bounding_rect, success_rect;
   CGContextRef context_ref;

   if( chnum == ' ' )
   {
      uni_char = 'n';
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
      uni_char = chnum;
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
   }
   else
   {
      uni_char = chnum;
      CTFontGetGlyphsForCharacters( ct_font, &uni_char, &glyph, count );
      success_rect = CTFontGetBoundingRectsForGlyphs( ct_font, kCTFontDefaultOrientation, &glyph, &bounding_rect, count );
   }

   if( CGRectEqualToRect( success_rect, CGRectNull ) == false )
   {
      size_t bitmap_width;
      size_t bitmap_height;

      bitmap_width = ceilf(bounding_rect.size.width * EXTRA_WIDTH);
      bitmap_width = bitmap_width == 0 ? 1 : bitmap_width;

      bitmap_height = ceilf( (CTFontGetAscent(ct_font) + CTFontGetDescent(ct_font) + CTFontGetLeading(ct_font)) * EXTRA_HEIGHT);

      xoffs = yoffs = 0;
      width = bitmap_width;

      size_t bits_per_component;
      CGColorSpaceRef color_space;
      CGBitmapInfo bitmap_info = kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst;

      color_space = CGColorSpaceCreateDeviceRGB();
      bits_per_component = 8;

      bitmap.allocate(bitmap_width, bitmap_height);

      context_ref = CGBitmapContextCreate( bitmap.raw_pixptr(0), bitmap_width, bitmap_height, bits_per_component, bitmap.rowpixels()*4, color_space, bitmap_info );

      if( context_ref != NULL )
      {
         CGFontRef font_ref;
         font_ref = CTFontCopyGraphicsFont( ct_font, NULL );
         CGContextSetTextPosition(context_ref, -bounding_rect.origin.x*EXTRA_WIDTH, CTFontGetDescent(ct_font)+CTFontGetLeading(ct_font) );
         CGContextSetRGBFillColor(context_ref, 1.0, 1.0, 1.0, 1.0);
         CGContextSetFont( context_ref, font_ref );
         CGContextSetFontSize( context_ref, POINT_SIZE );
         CGContextShowGlyphs( context_ref, &glyph, count );
         CGFontRelease( font_ref );
         CGContextRelease( context_ref );
      }

      CGColorSpaceRelease( color_space );
   }

   return bitmap.valid();
}
void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point)
{
    graphicsContext->save();
    
    wxGCDC* dc = static_cast<wxGCDC*>(graphicsContext->platformContext());

    wxFont* wxfont = font->getWxFont();
    graphicsContext->setFillColor(graphicsContext->fillColor(), DeviceColorSpace);

    CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext());

    CGFontRef cgFont;

#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT
    cgFont = CTFontCopyGraphicsFont((CTFontRef)wxfont->OSXGetCTFont(), NULL);
#else
    ATSFontRef fontRef;
    
    fontRef = FMGetATSFontRefFromFont(wxfont->MacGetATSUFontID());
    
    if (fontRef)
        cgFont = CGFontCreateWithPlatformFont((void*)&fontRef);
#endif
    
    CGContextSetFont(cgContext, cgFont);

    CGContextSetFontSize(cgContext, wxfont->GetPointSize());

    CGFloat red, green, blue, alpha;
    graphicsContext->fillColor().getRGBA(red, green, blue, alpha);
    CGContextSetRGBFillColor(cgContext, red, green, blue, alpha);

    CGAffineTransform matrix = CGAffineTransformIdentity;
    matrix.b = -matrix.b;
    matrix.d = -matrix.d;
    
    CGContextSetTextMatrix(cgContext, matrix);

    CGContextSetTextPosition(cgContext, point.x(), point.y());
    
    const FloatSize* advanceSizes = static_cast<const FloatSize*>(glyphBuffer.advances(from));
    int size = glyphBuffer.size() - from;
    CGSize sizes[size];
    CGGlyph glyphs[numGlyphs];
    
    // if the function doesn't exist, we're probably on tiger and need to grab the
    // function under its old name, CGFontGetGlyphsForUnicodes
    if (!CGFontGetGlyphsForUnichars)
        CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes");
    
    // Let's make sure we got the function under one name or another!
    ASSERT(CGFontGetGlyphsForUnichars);
    CGFontGetGlyphsForUnichars(cgFont, glyphBuffer.glyphs(from), glyphs, numGlyphs);
    
    for (int i = 0; i < size; i++) {
        FloatSize fsize = advanceSizes[i];
        sizes[i] = CGSizeMake(fsize.width(), fsize.height());
    }
    
    CGContextShowGlyphsWithAdvances(cgContext, glyphs, sizes, numGlyphs);
    
    if (cgFont)
        CGFontRelease(cgFont);
    graphicsContext->restore();
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

    Vector<CGGlyph, 512> glyphs(bufferLength);
    if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
        // We pass in either 256 or 512 UTF-16 characters: 256 for U+FFFF and less, 512 (double character surrogates)
        // for U+10000 and above. It is indeed possible to get back 512 glyphs back from the API, so the glyph buffer
        // we pass in must be 512. If we get back more than 256 glyphs though we'll ignore all the ones after 256,
        // this should not happen as the only time we pass in 512 characters is when they are surrogates.
        CGFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else if (!fontData->platformData().isCompositeFontReference() && ((fontData->platformData().widthVariant() == RegularWidth) ? wkGetVerticalGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength)
               : CTFontGetGlyphsForCharacters(fontData->platformData().ctFont(), buffer, glyphs.data(), bufferLength))) {
        // When buffer consists of surrogate pairs, wkGetVerticalGlyphsForCharacters and CTFontGetGlyphsForCharacters
        // place the glyphs at indices corresponding to the first character of each pair.
        unsigned glyphStep = bufferLength / length;
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i * glyphStep])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string = adoptCF(CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString = adoptCF(CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
        RetainPtr<CTLineRef> line = adoptCF(CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;

        // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
        // be non-CFEqual to fontData->platformData().cgFont().
        RetainPtr<CGFontRef> cgFont = adoptCF(CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0));

        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont = adoptCF(CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
            if (gotBaseFont || fontData->platformData().isCompositeFontReference()) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                if (gotBaseFont) {
                    for (CFIndex i = 0; i < glyphCount; ++i) {
                        if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                            done = true;
                            break;
                        }
                        if (glyphs[i]) {
                            setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                            haveGlyphs = true;
                        }
                    }
#if !PLATFORM(IOS)
                } else {
                    const SimpleFontData* runSimple = fontData->getCompositeFontReferenceFontData((NSFont *)runFont);
                    if (runSimple) {
                        for (CFIndex i = 0; i < glyphCount; ++i) {
                            if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                                done = true;
                                break;
                            }
                            if (glyphs[i]) {
                                setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
                                haveGlyphs = true;
                            }
                        }
                    }
#endif // !PLATFORM(IOS)
                }
            }
        }
    }

    return haveGlyphs;
}
CGFontRef FontPlatformData::cgFont() const
{
    return CTFontCopyGraphicsFont(ctFont(), 0);
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

#ifndef BUILDING_ON_TIGER
    if (fontData->orientation() == Horizontal || fontData->isBrokenIdeographFont()) {
        Vector<CGGlyph, 512> glyphs(bufferLength);
        wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0)));
        RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;
        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            if (CFEqual(fontData->platformData().cgFont(), runCGFont.get())) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                for (CFIndex i = 0; i < glyphCount; ++i) {
                    if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                        done = true;
                        break;
                    }
                    if (glyphs[i]) {
                        setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                        haveGlyphs = true;
                    }
                }
            }
        }
    }
#else
    // Use an array of long so we get good enough alignment.
    long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
    
    OSStatus status = wkInitializeGlyphVector(GlyphPage::size, &glyphVector);
    if (status != noErr)
        // This should never happen, perhaps indicates a bad font!  If it does the
        // font substitution code will find an alternate font.
        return false;

    wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);

    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
    if (numGlyphs != length) {
        // This should never happen, perhaps indicates a bad font?
        // If it does happen, the font substitution code will find an alternate font.
        wkClearGlyphVector(&glyphVector);
        return false;
    }

    ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
    for (unsigned i = 0; i < length; i++) {
        Glyph glyph = glyphRecord->glyphID;
        if (!glyph)
            setGlyphDataForIndex(offset + i, 0, 0);
        else {
            setGlyphDataForIndex(offset + i, glyph, fontData);
            haveGlyphs = true;
        }
        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
    }
    wkClearGlyphVector(&glyphVector);
#endif

    return haveGlyphs;
}
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    bool haveGlyphs = false;

    if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
        Vector<CGGlyph, 512> glyphs(bufferLength);

        CMFontGetGlyphsForUnichars(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
//        wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);

        for (unsigned i = 0; i < length; ++i) {
            if (!glyphs[i])
                setGlyphDataForIndex(offset + i, 0, 0);
            else {
                setGlyphDataForIndex(offset + i, glyphs[i], fontData);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal)));
        RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        // Initialize glyph entries
        for (unsigned index = 0; index < length; ++index)
            setGlyphDataForIndex(offset + index, 0, 0);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;

        // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
        // be non-CFEqual to fontData->platformData().cgFont().
        RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(fontData->platformData().ctFont(), 0));

        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., fontData->platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            if (CFEqual(cgFont.get(), runCGFont.get())) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                for (CFIndex i = 0; i < glyphCount; ++i) {
                    if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                        done = true;
                        break;
                    }
                    if (glyphs[i]) {
                        setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], fontData);
                        haveGlyphs = true;
                    }
                }
            }
        }
    }

    return haveGlyphs;
}
bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
{
    bool haveGlyphs = false;

    Vector<CGGlyph, 512> glyphs(bufferLength);
    if (!shouldUseCoreText(buffer, bufferLength, this)) {
        CGFontGetGlyphsForUnichars(platformData().cgFont(), buffer, glyphs.data(), bufferLength);
        for (unsigned i = 0; i < length; ++i) {
            if (glyphs[i]) {
                pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
                haveGlyphs = true;
            }
        }
    } else if (!platformData().isCompositeFontReference() && platformData().widthVariant() != RegularWidth
        && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
        // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters
        // places the glyphs at indices corresponding to the first character of each pair.
        unsigned glyphStep = bufferLength / length;
        for (unsigned i = 0; i < length; ++i) {
            if (glyphs[i * glyphStep]) {
                pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], this);
                haveGlyphs = true;
            }
        }
    } else {
        // We ask CoreText for possible vertical variant glyphs
        RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
        RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerticalGlyphs() ? Vertical : Horizontal)));
        RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));

        CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
        CFIndex runCount = CFArrayGetCount(runArray);

        Vector<CGGlyph, 512> glyphVector;
        Vector<CFIndex, 512> indexVector;
        bool done = false;

        // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
        // be non-CFEqual to platformData().cgFont().
        RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0));

        for (CFIndex r = 0; r < runCount && !done ; ++r) {
            // CTLine could map characters over multiple fonts using its own font fallback list.
            // We need to pick runs that use the exact font we need, i.e., platformData().ctFont().
            CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
            ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());

            CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
            CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
            RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
            // Use CGFont here as CFEqual for CTFont counts all attributes for font.
            bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
            if (gotBaseFont || platformData().isCompositeFontReference()) {
                // This run uses the font we want. Extract glyphs.
                CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
                const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
                if (!glyphs) {
                    glyphVector.resize(glyphCount);
                    CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
                    glyphs = glyphVector.data();
                }
                const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
                if (!stringIndices) {
                    indexVector.resize(glyphCount);
                    CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
                    stringIndices = indexVector.data();
                }

                if (gotBaseFont) {
                    for (CFIndex i = 0; i < glyphCount; ++i) {
                        if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                            done = true;
                            break;
                        }
                        if (glyphs[i]) {
                            pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], this);
                            haveGlyphs = true;
                        }
                    }
                } else {
                    const SimpleFontData* runSimple = getCompositeFontReferenceFontData((NSFont *)runFont);
                    if (runSimple) {
                        for (CFIndex i = 0; i < glyphCount; ++i) {
                            if (stringIndices[i] >= static_cast<CFIndex>(length)) {
                                done = true;
                                break;
                            }
                            if (glyphs[i]) {
                                pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
                                haveGlyphs = true;
                            }
                        }
                    }
                }
            }
        }
    }

    return haveGlyphs;
}