unsafe fn layout_text(&mut self, request: LayoutRequest) -> NodeLayout {
        let mut totalGlyphCount;
        let mut glyphAdvances: *mut Scaled = ptr::null_mut();
        let mut glyph_info: *mut libc::c_void = ptr::null_mut();
        let mut locations: *mut FixedPoint = ptr::null_mut();
        let mut width: CGFloat = 0.;
        let typesetter;
        let mut line;

        let txtLen = request.text.len() as CFIndex;
        let txtPtr: *const UniChar = request.text.as_ptr();
        let justify = request.justify;

        let mut layout = NodeLayout {
            lsDelta: None,
            width: Scaled::ZERO,
            total_glyph_count: 0,
            glyph_info: ptr::null_mut(),
        };

        let string =
            CFStringCreateWithCharactersNoCopy(ptr::null(), txtPtr, txtLen, kCFAllocatorNull);
        let attrString = CFAttributedStringCreate(ptr::null(), string, self.attributes);
        CFRelease(string as CFTypeRef);
        typesetter = CTTypesetterCreateWithAttributedString(attrString);
        CFRelease(attrString as CFTypeRef);
        line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, txtLen));
        if justify {
            let lineWidth = TeXtoPSPoints(request.line_width.into());
            let justifiedLine = CTLineCreateJustifiedLine(
                line,
                TeXtoPSPoints(Scaled(0x40000000).into()),
                lineWidth,
            );
            // TODO(jjgod): how to handle the case when justification failed? for
            // now we just fallback to use the original line.
            if !justifiedLine.is_null() {
                CFRelease(line as CFTypeRef);
                line = justifiedLine
            }
        }
        let glyphRuns = CTLineGetGlyphRuns(line);
        let runCount = CFArrayGetCount(glyphRuns);
        totalGlyphCount = CTLineGetGlyphCount(line) as usize;
        if totalGlyphCount > 0 {
            glyph_info = xmalloc(
                (totalGlyphCount * (std::mem::size_of::<FixedPoint>() + std::mem::size_of::<u16>()))
                    as _,
            );
            locations = glyph_info as *mut FixedPoint;
            let glyphIDs = locations.add(totalGlyphCount) as *mut u16;
            glyphAdvances =
                xmalloc(totalGlyphCount.wrapping_mul(::std::mem::size_of::<Scaled>()) as _)
                    as *mut Scaled;
            totalGlyphCount = 0;
            width = 0.;
            for i in 0..runCount {
                let run = CFArrayGetValueAtIndex(glyphRuns, i) as CTRunRef;
                let count = CTRunGetGlyphCount(run) as usize;
                let runAttributes = CTRunGetAttributes(run);
                let vertical = CFDictionaryGetValue(
                    runAttributes,
                    kCTVerticalFormsAttributeName as *const libc::c_void,
                ) as CFBooleanRef;
                // TODO(jjgod): Avoid unnecessary allocation with CTRunGetFoosPtr().
                let mut glyphs = vec![0 as CGGlyph; count];
                let mut positions = vec![CGPoint::new(0., 0.); count];
                let mut advances = vec![CGSize::new(0., 0.); count];
                let runWidth = CTRunGetTypographicBounds(
                    run,
                    CFRangeMake(0, 0),
                    ptr::null_mut(),
                    ptr::null_mut(),
                    ptr::null_mut(),
                );
                CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs.as_mut_ptr());
                CTRunGetPositions(run, CFRangeMake(0, 0), positions.as_mut_ptr());
                CTRunGetAdvances(run, CFRangeMake(0, 0), advances.as_mut_ptr());
                for j in 0..count {
                    // XXX Core Text has that font cascading thing that will do
                    // font substitution for missing glyphs, which we do not want
                    // but I can not find a way to disable it yet, so if the font
                    // of the resulting run is not the same font we asked for, use
                    // the glyph at index 0 (usually .notdef) instead or we will be
                    // showing garbage or even invalid glyphs
                    *glyphIDs.add(totalGlyphCount) = if CFEqual(
                        font_from_attributes(self.attributes) as CFTypeRef,
                        font_from_attributes(runAttributes) as CFTypeRef,
                    ) == 0
                    {
                        0
                    } else {
                        glyphs[j]
                    };
                    // Swap X and Y when doing vertical layout
                    if vertical == kCFBooleanTrue {
                        (*locations.add(totalGlyphCount)).x = -FixedPStoTeXPoints(positions[j].y);
                        (*locations.add(totalGlyphCount)).y = FixedPStoTeXPoints(positions[j].x)
                    } else {
                        (*locations.add(totalGlyphCount)).x = FixedPStoTeXPoints(positions[j].x);
                        (*locations.add(totalGlyphCount)).y = -FixedPStoTeXPoints(positions[j].y)
                    }
                    *glyphAdvances.offset(totalGlyphCount as isize) =
                        Scaled(advances[j].width as i32);
                    totalGlyphCount += 1;
                }
                width += FixedPStoTeXPoints(runWidth).0 as f64;
            }
        }

        layout.total_glyph_count = totalGlyphCount as u16;
        layout.glyph_info = glyph_info as *mut _;

        if !justify {
            layout.width = Scaled(width as i32);
            if totalGlyphCount > 0 {
                /* this is essentially a copy from similar code in XeTeX_ext.c, easier
                 * to be done here */
                if request.letter_space_unit != Scaled::ZERO {
                    let mut lsDelta = Scaled::ZERO;
                    let lsUnit = request.letter_space_unit;
                    for i_0 in 0..totalGlyphCount {
                        if *glyphAdvances.add(i_0) == Scaled::ZERO && lsDelta != Scaled::ZERO {
                            lsDelta -= lsUnit
                        }
                        let ref mut fresh1 = (*locations.add(i_0)).x;
                        *fresh1 += lsDelta;
                        lsDelta += lsUnit;
                    }
                    if lsDelta != Scaled::ZERO {
                        lsDelta -= lsUnit;
                        layout.lsDelta = Some(lsDelta);
                    }
                }
            }
        }
        free(glyphAdvances as *mut libc::c_void);
        CFRelease(line as CFTypeRef);
        CFRelease(typesetter as CFTypeRef);
        layout
    }
/// The most important trait method. Lay out some text and return its size.
The most important trait method. Lay out some text and return its size.
The most important trait method . Lay out some text and return its size .
unsafe fn layout_text(&mut self, request: LayoutRequest) -> NodeLayout {
        let mut totalGlyphCount;
        let mut glyphAdvances: *mut Scaled = ptr::null_mut();
        let mut glyph_info: *mut libc::c_void = ptr::null_mut();
        let mut locations: *mut FixedPoint = ptr::null_mut();
        let mut width: CGFloat = 0.;
        let typesetter;
        let mut line;
        let txtLen = request.text.len() as CFIndex;
        let txtPtr: *const UniChar = request.text.as_ptr();
        let justify = request.justify;
        let mut layout = NodeLayout {
            lsDelta: None,
            width: Scaled::ZERO,
            total_glyph_count: 0,
            glyph_info: ptr::null_mut(),
        };
        let string =
            CFStringCreateWithCharactersNoCopy(ptr::null(), txtPtr, txtLen, kCFAllocatorNull);
        let attrString = CFAttributedStringCreate(ptr::null(), string, self.attributes);
        CFRelease(string as CFTypeRef);
        typesetter = CTTypesetterCreateWithAttributedString(attrString);
        CFRelease(attrString as CFTypeRef);
        line = CTTypesetterCreateLine(typesetter, CFRangeMake(0, txtLen));
        if justify {
            let lineWidth = TeXtoPSPoints(request.line_width.into());
            let justifiedLine = CTLineCreateJustifiedLine(
                line,
                TeXtoPSPoints(Scaled(0x40000000).into()),
                lineWidth,
            );
            // TODO(jjgod): how to handle the case when justification failed? for
            // now we just fallback to use the original line.
            if !justifiedLine.is_null() {
                CFRelease(line as CFTypeRef);
                line = justifiedLine
            }
        }
        let glyphRuns = CTLineGetGlyphRuns(line);
        let runCount = CFArrayGetCount(glyphRuns);
        totalGlyphCount = CTLineGetGlyphCount(line) as usize;
        if totalGlyphCount > 0 {
            glyph_info = xmalloc(
                (totalGlyphCount * (std::mem::size_of::<FixedPoint>() + std::mem::size_of::<u16>()))
                    as _,
            );
            locations = glyph_info as *mut FixedPoint;
            let glyphIDs = locations.add(totalGlyphCount) as *mut u16;
            glyphAdvances =
                xmalloc(totalGlyphCount.wrapping_mul(::std::mem::size_of::<Scaled>()) as _)
                    as *mut Scaled;
            totalGlyphCount = 0;
            width = 0.;
            for i in 0..runCount {
                let run = CFArrayGetValueAtIndex(glyphRuns, i) as CTRunRef;
                let count = CTRunGetGlyphCount(run) as usize;
                let runAttributes = CTRunGetAttributes(run);
                let vertical = CFDictionaryGetValue(
                    runAttributes,
                    kCTVerticalFormsAttributeName as *const libc::c_void,
                ) as CFBooleanRef;
                // TODO(jjgod): Avoid unnecessary allocation with CTRunGetFoosPtr().
                let mut glyphs = vec![0 as CGGlyph; count];
                let mut positions = vec![CGPoint::new(0., 0.); count];
                let mut advances = vec![CGSize::new(0., 0.); count];
                let runWidth = CTRunGetTypographicBounds(
                    run,
                    CFRangeMake(0, 0),
                    ptr::null_mut(),
                    ptr::null_mut(),
                    ptr::null_mut(),
                );
                CTRunGetGlyphs(run, CFRangeMake(0, 0), glyphs.as_mut_ptr());
                CTRunGetPositions(run, CFRangeMake(0, 0), positions.as_mut_ptr());
                CTRunGetAdvances(run, CFRangeMake(0, 0), advances.as_mut_ptr());
                for j in 0..count {
                    // XXX Core Text has that font cascading thing that will do
                    // font substitution for missing glyphs, which we do not want
                    // but I can not find a way to disable it yet, so if the font
                    // of the resulting run is not the same font we asked for, use
                    // the glyph at index 0 (usually .notdef) instead or we will be
                    // showing garbage or even invalid glyphs
                    *glyphIDs.add(totalGlyphCount) = if CFEqual(
                        font_from_attributes(self.attributes) as CFTypeRef,
                        font_from_attributes(runAttributes) as CFTypeRef,
                    ) == 0
                    {
                        0
                    } else {
                        glyphs[j]
                    };
                    // Swap X and Y when doing vertical layout
                    if vertical == kCFBooleanTrue {
                        (*locations.add(totalGlyphCount)).x = -FixedPStoTeXPoints(positions[j].y);
                        (*locations.add(totalGlyphCount)).y = FixedPStoTeXPoints(positions[j].x)
                    } else {
                        (*locations.add(totalGlyphCount)).x = FixedPStoTeXPoints(positions[j].x);
                        (*locations.add(totalGlyphCount)).y = -FixedPStoTeXPoints(positions[j].y)
                    }
                    *glyphAdvances.offset(totalGlyphCount as isize) =
                        Scaled(advances[j].width as i32);
                    totalGlyphCount += 1;
                }
                width += FixedPStoTeXPoints(runWidth).0 as f64;
            }
        }
        layout.total_glyph_count = totalGlyphCount as u16;
        layout.glyph_info = glyph_info as *mut _;
        if !justify {
            layout.width = Scaled(width as i32);
            if totalGlyphCount > 0 {
                /* this is essentially a copy from similar code in XeTeX_ext.c, easier
                 * to be done here */
                if request.letter_space_unit != Scaled::ZERO {
                    let mut lsDelta = Scaled::ZERO;
                    let lsUnit = request.letter_space_unit;
                    for i_0 in 0..totalGlyphCount {
                        if *glyphAdvances.add(i_0) == Scaled::ZERO && lsDelta != Scaled::ZERO {
                            lsDelta -= lsUnit
                        }
                        let ref mut fresh1 = (*locations.add(i_0)).x;
                        *fresh1 += lsDelta;
                        lsDelta += lsUnit;
                    }
                    if lsDelta != Scaled::ZERO {
                        lsDelta -= lsUnit;
                        layout.lsDelta = Some(lsDelta);
                    }
                }
            }
        }
        free(glyphAdvances as *mut libc::c_void);
        CFRelease(line as CFTypeRef);
        CFRelease(typesetter as CFTypeRef);
        layout
    }
unsafe fn layout_text ( & mut self , request : LayoutRequest ) -> NodeLayout { let mut totalGlyphCount ; let mut glyphAdvances : * mut Scaled = ptr :: null_mut ( ) ; let mut glyph_info : * mut libc :: c_void = ptr :: null_mut ( ) ; let mut locations : * mut FixedPoint = ptr :: null_mut ( ) ; let mut width : CGFloat = 0. ; let typesetter ; let mut line ; let txtLen = request . text . len ( ) as CFIndex ; let txtPtr : * const UniChar = request . text . as_ptr ( ) ; let justify = request . justify ; let mut layout = NodeLayout { lsDelta : None , width : Scaled :: ZERO , total_glyph_count : 0 , glyph_info : ptr :: null_mut ( ) , } ; let string = CFStringCreateWithCharactersNoCopy ( ptr :: null ( ) , txtPtr , txtLen , kCFAllocatorNull ) ; let attrString = CFAttributedStringCreate ( ptr :: null ( ) , string , self . attributes ) ; CFRelease ( string as CFTypeRef ) ; typesetter = CTTypesetterCreateWithAttributedString ( attrString ) ; CFRelease ( attrString as CFTypeRef ) ; line = CTTypesetterCreateLine ( typesetter , CFRangeMake ( 0 , txtLen ) ) ; if justify { let lineWidth = TeXtoPSPoints ( request . line_width . into ( ) ) ; let justifiedLine = CTLineCreateJustifiedLine ( line , TeXtoPSPoints ( Scaled ( 0x40000000 ) . into ( ) ) , lineWidth , ) ; // TODO(jjgod): how to handle the case when justification failed? for // now we just fallback to use the original line. if ! justifiedLine . is_null ( ) { CFRelease ( line as CFTypeRef ) ; line = justifiedLine } } let glyphRuns = CTLineGetGlyphRuns ( line ) ; let runCount = CFArrayGetCount ( glyphRuns ) ; totalGlyphCount = CTLineGetGlyphCount ( line ) as usize ; if totalGlyphCount > 0 { glyph_info = xmalloc ( ( totalGlyphCount * ( std :: mem :: size_of :: < FixedPoint > ( ) + std :: mem :: size_of :: < u16 > ( ) ) ) as _ , ) ; locations = glyph_info as * mut FixedPoint ; let glyphIDs = locations . add ( totalGlyphCount ) as * mut u16 ; glyphAdvances = xmalloc ( totalGlyphCount . wrapping_mul ( :: std :: mem :: size_of :: < Scaled > ( ) ) as _ ) as * mut Scaled ; totalGlyphCount = 0 ; width = 0. ; for i in 0 .. runCount { let run = CFArrayGetValueAtIndex ( glyphRuns , i ) as CTRunRef ; let count = CTRunGetGlyphCount ( run ) as usize ; let runAttributes = CTRunGetAttributes ( run ) ; let vertical = CFDictionaryGetValue ( runAttributes , kCTVerticalFormsAttributeName as * const libc :: c_void , ) as CFBooleanRef ; // TODO(jjgod): Avoid unnecessary allocation with CTRunGetFoosPtr(). let mut glyphs = vec ! [ 0 as CGGlyph count ] ; let mut positions = vec ! [ CGPoint new ( 0. 0. ) count ] ; let mut advances = vec ! [ CGSize new ( 0. 0. ) count ] ; let runWidth = CTRunGetTypographicBounds ( run , CFRangeMake ( 0 , 0 ) , ptr :: null_mut ( ) , ptr :: null_mut ( ) , ptr :: null_mut ( ) , ) ; CTRunGetGlyphs ( run , CFRangeMake ( 0 , 0 ) , glyphs . as_mut_ptr ( ) ) ; CTRunGetPositions ( run , CFRangeMake ( 0 , 0 ) , positions . as_mut_ptr ( ) ) ; CTRunGetAdvances ( run , CFRangeMake ( 0 , 0 ) , advances . as_mut_ptr ( ) ) ; for j in 0 .. count { // XXX Core Text has that font cascading thing that will do // font substitution for missing glyphs, which we do not want // but I can not find a way to disable it yet, so if the font // of the resulting run is not the same font we asked for, use // the glyph at index 0 (usually .notdef) instead or we will be // showing garbage or even invalid glyphs * glyphIDs . add ( totalGlyphCount ) = if CFEqual ( font_from_attributes ( self . attributes ) as CFTypeRef , font_from_attributes ( runAttributes ) as CFTypeRef , ) == 0 { 0 } else { glyphs [ j ] } ; // Swap X and Y when doing vertical layout if vertical == kCFBooleanTrue { ( * locations . add ( totalGlyphCount ) ) . x = - FixedPStoTeXPoints ( positions [ j ] . y ) ; ( * locations . add ( totalGlyphCount ) ) . y = FixedPStoTeXPoints ( positions [ j ] . x ) } else { ( * locations . add ( totalGlyphCount ) ) . x = FixedPStoTeXPoints ( positions [ j ] . x ) ; ( * locations . add ( totalGlyphCount ) ) . y = - FixedPStoTeXPoints ( positions [ j ] . y ) } * glyphAdvances . offset ( totalGlyphCount as isize ) = Scaled ( advances [ j ] . width as i32 ) ; totalGlyphCount += 1 ; } width += FixedPStoTeXPoints ( runWidth ) . 0 as f64 ; } } layout . total_glyph_count = totalGlyphCount as u16 ; layout . glyph_info = glyph_info as * mut _ ; if ! justify { layout . width = Scaled ( width as i32 ) ; if totalGlyphCount > 0 { /* this is essentially a copy from similar code in XeTeX_ext.c, easier
                 * to be done here */ if request . letter_space_unit != Scaled :: ZERO { let mut lsDelta = Scaled :: ZERO ; let lsUnit = request . letter_space_unit ; for i_0 in 0 .. totalGlyphCount { if * glyphAdvances . add ( i_0 ) == Scaled :: ZERO && lsDelta != Scaled :: ZERO { lsDelta -= lsUnit } let ref mut fresh1 = ( * locations . add ( i_0 ) ) . x ; * fresh1 += lsDelta ; lsDelta += lsUnit ; } if lsDelta != Scaled :: ZERO { lsDelta -= lsUnit ; layout . lsDelta = Some ( lsDelta ) ; } } } } free ( glyphAdvances as * mut libc :: c_void ) ; CFRelease ( line as CFTypeRef ) ; CFRelease ( typesetter as CFTypeRef ) ; layout }
The most important trait method.
The most important trait method .
&mut self
request
LayoutRequest