bool CGRect::CGRectIntersectsRect(const CGRect& rectA, const CGRect& rectB) { return !(CGRectGetMaxX(rectA) < CGRectGetMinX(rectB)|| CGRectGetMaxX(rectB) < CGRectGetMinX(rectA)|| CGRectGetMaxY(rectA) < CGRectGetMinY(rectB)|| CGRectGetMaxY(rectB) < CGRectGetMinY(rectB)); }
static void ButtonElementSize( void *clientData, void *elementRecord, Tk_Window tkwin, int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr) { ThemeButtonParams *params = clientData; const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds; ButtonElementSizeNoPadding( clientData, elementRecord, tkwin, widthPtr, heightPtr, paddingPtr); /* * To compute internal padding, query the appearance manager * for the content bounds of a dummy rectangle, then use * the difference as the padding. */ ChkErr(HIThemeGetButtonContentBounds, &scratchBounds, &info, &contentBounds); paddingPtr->left = CGRectGetMinX(contentBounds); paddingPtr->top = CGRectGetMinY(contentBounds); paddingPtr->right = CGRectGetMaxX(scratchBounds) - CGRectGetMaxX(contentBounds) + 1; paddingPtr->bottom = CGRectGetMaxY(scratchBounds) - CGRectGetMaxY(contentBounds); /* * Now add a little extra padding to account for drop shadows. * @@@ SHOULD: call GetThemeButtonBackgroundBounds() instead. */ *paddingPtr = Ttk_AddPadding(*paddingPtr, ButtonMargins); *widthPtr += Ttk_PaddingWidth(ButtonMargins); *heightPtr += Ttk_PaddingHeight(ButtonMargins); }
// ----------------------------------------------------------------------------- // HITestViewGetRegion // ----------------------------------------------------------------------------- // OSStatus HITestViewGetRegion( EventRef inEvent, HITestViewData* inData ) { OSStatus err; ControlPartCode part; RgnHandle outRegion; HIRect bounds; Rect qdBounds; err = GetEventParameter( inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof( ControlPartCode ), NULL, &part ); require_noerr( err, ParameterMissing ); err = GetEventParameter( inEvent, kEventParamControlRegion, typeQDRgnHandle, NULL, sizeof( RgnHandle ), NULL, &outRegion ); if ( part == kControlContentMetaPart || part == kControlStructureMetaPart /* || part == kControlOpaqueRegionMetaPart */ ) { HIViewGetBounds( inData->view, &bounds ); qdBounds.top = (SInt16) CGRectGetMinY( bounds ); qdBounds.left = (SInt16) CGRectGetMinX( bounds ); qdBounds.bottom = (SInt16) CGRectGetMaxY( bounds ); qdBounds.right = (SInt16) CGRectGetMaxX( bounds ); RectRgn( outRegion, &qdBounds ); } ParameterMissing: return err; }
CGFloat CBRectPointDistance(CGRect rect, CGPoint point) { CGPoint p00 = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect)); CGPoint p11 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect)); if (point.x < p00.x) { if (point.y < p00.y) return CBPointPointDistance(point, p00); else if (point.y > p11.y) return CBPointPointDistance(point, CGPointMake(p00.x, p11.y)); else return p00.x - point.x; } if (point.x > p11.x) { if (point.y < p00.y) return CBPointPointDistance(point, CGPointMake(p11.x, p00.y)); else if (point.y > p11.y) return CBPointPointDistance(point, p11); else return point.x - p11.x; } if (point.y < p00.y) return p00.y - point.y; else if (point.y > p11.y) return point.y - p11.y; return 0.0; }
CGPoint CGLineIntersectsRectAtPoint(CGRect rect, CGLine line) { CGLine top = CGLineMake( CGPointMake( CGRectGetMinX(rect), CGRectGetMinY(rect) ), CGPointMake( CGRectGetMaxX(rect), CGRectGetMinY(rect) ) ); CGLine right = CGLineMake( CGPointMake( CGRectGetMaxX(rect), CGRectGetMinY(rect) ), CGPointMake( CGRectGetMaxX(rect), CGRectGetMaxY(rect) ) ); CGLine bottom = CGLineMake( CGPointMake( CGRectGetMinX(rect), CGRectGetMaxY(rect) ), CGPointMake( CGRectGetMaxX(rect), CGRectGetMaxY(rect) ) ); CGLine left = CGLineMake( CGPointMake( CGRectGetMinX(rect), CGRectGetMinY(rect) ), CGPointMake( CGRectGetMinX(rect), CGRectGetMaxY(rect) ) ); // ensure the line extends beyond outside the rectangle CGFloat topLeftToBottomRight = CGPointDistance(CGRectTopLeftPoint(rect), CGRectBottomRightPoint(rect)); CGFloat bottomLeftToTopRight = CGPointDistance(CGRectBottomLeftPoint(rect), CGRectTopRightPoint(rect)); CGFloat maxDimension = MT_MAX(topLeftToBottomRight, bottomLeftToTopRight); CGFloat scaleFactor = maxDimension / MT_MIN(CGLineLength(line), maxDimension); CGLine extendedLine = CGLineScale(line, scaleFactor + 3); CGPoint points[4] = { CGLinesIntersectAtPoint(top, extendedLine), CGLinesIntersectAtPoint(right, extendedLine), CGLinesIntersectAtPoint(bottom, extendedLine), CGLinesIntersectAtPoint(left, extendedLine) }; for (int i = 0; i < 4; i++) { CGPoint p = points[i]; if (!CGPointEqualToPoint(p, NULL_POINT)) { return p; } } return NULL_POINT; }
IntRect enclosingIntRect(const CGRect& rect) { int l = static_cast<int>(floorf(rect.origin.x)); int t = static_cast<int>(floorf(rect.origin.y)); int r = static_cast<int>(ceilf(CGRectGetMaxX(rect))); int b = static_cast<int>(ceilf(CGRectGetMaxY(rect))); return IntRect(l, t, r - l, b - t); }
void drawRoundedRect(CGContextRef context, CGRect rrect) { // Drawing with a white stroke color CGContextSetRGBStrokeColor(context, 0.3, 0.3, 0.3, 1.0); CGContextSetRGBFillColor(context, 0.3, 0.3, 0.3, 1.0); // Add Rect to the current path, then stroke it // CGContextAddRect(context, CGRectMake(10.0, 190.0, 290.0, 73.0)); CGContextSetLineWidth(context, 1); CGFloat radius = 10.0; CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); // Next, we will go around the rectangle in the order given by the figure below. // minx midx maxx // miny 2 3 4 // midy 1 9 5 // maxy 8 7 6 // Which gives us a coincident start and end point, which is incidental to this technique, but still doesn't // form a closed path, so we still need to close the path to connect the ends correctly. // Thus we start by moving to point 1, then adding arcs through each pair of points that follows. // You could use a similar tecgnique to create any shape with rounded corners. // Start at 1 CGContextMoveToPoint(context, minx, midy); // Add an arc through 2 to 3 CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); // Add an arc through 4 to 5 CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); // Add an arc through 6 to 7 CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); // Add an arc through 8 to 9 CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); // Close the path CGContextClosePath(context); // Fill & stroke the path CGContextDrawPath(context, kCGPathFillStroke); CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 0.0); CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); CGContextMoveToPoint(context, minx, midy); // Add an arc through 2 to 3 CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); // Add an arc through 4 to 5 CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); // Add an arc through 6 to 7 CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); // Add an arc through 8 to 9 CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); // Close the path CGContextClosePath(context); // Fill & stroke the path CGContextDrawPath(context, kCGPathFillStroke); }
// ----------------------------------------------------------------------------- // ShadeRectColor // ----------------------------------------------------------------------------- // OSStatus ShadeRectColor( const CGRGB* inStartColor, const CGRGB* inEndColor, const HIRect* inRect, CGContextRef inContext ) { OSStatus err = noErr; CGColorSpaceRef colorSpace; CGFunctionCallbacks callbacks = { 0, ColorGradientEvaluate, NULL }; CGFunctionRef function; CGShadingRef shading; ColorShadeData data; // Warning: this stuff is sitting on the stack. Be careful if you move // the shading code around. data.start = *inStartColor; data.range.red = inEndColor->red - inStartColor->red; data.range.green = inEndColor->green - inStartColor->green; data.range.blue = inEndColor->blue - inStartColor->blue; CGContextSaveGState( inContext ); CGContextClipToRect( inContext, *inRect ); colorSpace = CGColorSpaceCreateDeviceRGB(); require_action( colorSpace != NULL, CantCreateColorSpace, err = memFullErr ); function = CGFunctionCreate( &data, // info 1, // domainDimension NULL, // input domain NULL == no range clipping 4, // rangeDimension, NULL, // output domain NULL == no range clipping &callbacks ); // CGFunctionCallbacks require_action( function != NULL, CantCreateFunction, err = memFullErr ); shading = CGShadingCreateAxial( colorSpace, inRect->origin, // start CGPointMake( CGRectGetMinX( *inRect ), CGRectGetMaxY( *inRect ) ), // end function, false, // extendStart false ); // extendEnd require_action( colorSpace != NULL, CantCreateShading, err = memFullErr ); CGContextDrawShading( inContext, shading); CantCreateFunction: CGShadingRelease( shading ); CantCreateShading: CGColorSpaceRelease( colorSpace ); CantCreateColorSpace: CGContextRestoreGState( inContext ); return err; }
/* Return dimensions of current main display as an array of two integers */ VALUE MW_display_size(VALUE module) { CGRect bounds; VALUE retval; bounds = CGDisplayBounds(CGMainDisplayID()); retval = rb_ary_new(); rb_ary_push(retval, INT2NUM((int)CGRectGetMaxX(bounds))); rb_ary_push(retval, INT2NUM((int)CGRectGetMaxY(bounds))); return retval; }
bool CGRect::CGRectContainsPoint(const CGRect& rect, const CGPoint& point) { bool bRet = false; if (point.x >= CGRectGetMinX(rect) && point.x <= CGRectGetMaxX(rect) && point.y >= CGRectGetMinY(rect) && point.y <= CGRectGetMaxY(rect)) { bRet = true; } return bRet; }
void QuartzWindow::get_window_region_rect(int wh, Rect* r) { HIRect bounds; OSStatus err = HIWindowGetBounds(my_window(), wh, kHICoordSpace72DPIGlobal, &bounds); if (err) { lprintf("HIWindowGetBounds failed: %d\n", err); r->left = r->top = 0; r->bottom = r->right = 1; } else { r->left = (short) CGRectGetMinX(bounds); r->top = (short) CGRectGetMinY(bounds); r->bottom = (short) CGRectGetMaxY(bounds); r->right = (short) CGRectGetMaxX(bounds); } }
void addRoundedRectToPath(CGContextRef context, CGRect rect, CGFloat radius) { CGFloat minX = CGRectGetMinX(rect); CGFloat minY = CGRectGetMinY(rect); CGFloat maxX = CGRectGetMaxX(rect); CGFloat maxY = CGRectGetMaxY(rect); CGFloat midX = CGRectGetMidX(rect); CGFloat midY = CGRectGetMidY(rect); CGContextBeginPath(context); CGContextMoveToPoint(context, maxX, midY); CGContextAddArcToPoint(context, maxX, maxY, midX, maxY, radius); CGContextAddArcToPoint(context, minX, maxY, minX, midY, radius); CGContextAddArcToPoint(context, minX, minY, midX, minY, radius); CGContextAddArcToPoint(context, maxX, minY, maxX, midY, radius); CGContextClosePath(context); }
/*********************************************************************** * create_surface_image * * Caller must hold the surface lock. On input, *rect is the requested * image rect, relative to the window whole_rect, a.k.a. visible_rect. * On output, it's been intersected with that part backed by the surface * and is the actual size of the returned image. copy_data indicates if * the caller will keep the returned image beyond the point where the * surface bits can be guaranteed to remain valid and unchanged. If so, * the bits are copied instead of merely referenced by the image. * * IMPORTANT: This function is called from non-Wine threads, so it * must not use Win32 or Wine functions, including debug * logging. */ CGImageRef create_surface_image(void *window_surface, CGRect *rect, int copy_data) { CGImageRef cgimage = NULL; struct macdrv_window_surface *surface = get_mac_surface(window_surface); int width, height; width = surface->header.rect.right - surface->header.rect.left; height = surface->header.rect.bottom - surface->header.rect.top; *rect = CGRectIntersection(cgrect_from_rect(surface->header.rect), *rect); if (!CGRectIsEmpty(*rect)) { CGRect visrect; CGColorSpaceRef colorspace; CGDataProviderRef provider; int bytes_per_row, offset, size; CGImageAlphaInfo alphaInfo; visrect = CGRectOffset(*rect, -surface->header.rect.left, -surface->header.rect.top); colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); bytes_per_row = get_dib_stride(width, 32); offset = CGRectGetMinX(visrect) * 4 + (height - CGRectGetMaxY(visrect)) * bytes_per_row; size = min(CGRectGetHeight(visrect) * bytes_per_row, surface->info.bmiHeader.biSizeImage - offset); if (copy_data) { CFDataRef data = CFDataCreate(NULL, (UInt8*)surface->bits + offset, size); provider = CGDataProviderCreateWithCFData(data); CFRelease(data); } else provider = CGDataProviderCreateWithData(NULL, surface->bits + offset, size, NULL); alphaInfo = surface->use_alpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst; cgimage = CGImageCreate(CGRectGetWidth(visrect), CGRectGetHeight(visrect), 8, 32, bytes_per_row, colorspace, alphaInfo | kCGBitmapByteOrder32Little, provider, NULL, FALSE, kCGRenderingIntentDefault); CGDataProviderRelease(provider); CGColorSpaceRelease(colorspace); } return cgimage; }
void infoDisplays(void) { CGDisplayErr dErr; CGDisplayCount displayCount, i; CGDirectDisplayID mainDisplay; CGDisplayCount maxDisplays = MAX_DISPLAYS; CGDirectDisplayID onlineDisplays[MAX_DISPLAYS]; CGEventRef ourEvent = CGEventCreate(NULL); CGPoint ourLoc = CGEventGetLocation(ourEvent); CFRelease(ourEvent); mainDisplay = CGMainDisplayID(); dErr = CGGetOnlineDisplayList(maxDisplays, onlineDisplays, &displayCount); if (dErr != kCGErrorSuccess) { fprintf(stderr, "CGGetOnlineDisplayList: error %d.\n", dErr); exit(1); } printf("# Display_ID Resolution ____Display_Bounds____ Rotation\n"); for (i = 0; i < displayCount; i++) { CGDirectDisplayID dID = onlineDisplays[i]; printf("%-2d %10p %4lux%-4lu %5.0f %5.0f %5.0f %5.0f %3.0f %s%s%s", CGDisplayUnitNumber (dID), dID, CGDisplayPixelsWide(dID), CGDisplayPixelsHigh(dID), CGRectGetMinX (CGDisplayBounds (dID)), CGRectGetMinY (CGDisplayBounds (dID)), CGRectGetMaxX (CGDisplayBounds (dID)), CGRectGetMaxY (CGDisplayBounds (dID)), CGDisplayRotation (dID), (CGDisplayIsActive (dID)) ? "" : "[inactive]", (dID == mainDisplay) ? "[main]" : "", (CGDisplayIsBuiltin (dID)) ? "[internal]\n" : "\n"); } printf("Mouse Cursor Position: ( %5.0f , %5.0f )\n", (float)ourLoc.x, (float)ourLoc.y); exit(0); }
oop GetWindowRegion_wrap( WindowRef w, uint16 reg, void* FH) { // // TODO: GetWindoRegion is deprecated and not avialiable in >=10.7 // For now, we emulate with HIWindowGetBounds // HIRect bounds; OSStatus err = HIWindowGetBounds((WindowRef)w, reg, kHICoordSpace72DPIGlobal, &bounds); if (err) { return (oop)reportOSError(err, "GetWindowRegion", FH); } objVectorOop r = Memory->objVectorObj->cloneSize(4); // r->obj_at_put(0, as_floatOop(CGRectGetMinX(bounds)), false); // r->obj_at_put(1, as_floatOop(CGRectGetMinY(bounds)), false); // r->obj_at_put(2, as_floatOop(CGRectGetMaxX(bounds)), false); // r->obj_at_put(3, as_floatOop(CGRectGetMaxY(bounds)), false); r->obj_at_put(0, as_smiOop((short)CGRectGetMinX(bounds)), false); r->obj_at_put(1, as_smiOop((short)CGRectGetMinY(bounds)), false); r->obj_at_put(2, as_smiOop((short)CGRectGetMaxX(bounds)), false); r->obj_at_put(3, as_smiOop((short)CGRectGetMaxY(bounds)), false); return r; }
CGPoint CGRectBottomRightPoint(CGRect rect) { return CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect)); }
static cairo_int_status_t _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); int advance; CGRect bbox; double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); double xmin, ymin, xmax, ymax; if (glyph == INVALID_GLYPH) goto FAIL; if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) goto FAIL; /* broken fonts like Al Bayan return incorrect bounds for some null characters, see https://bugzilla.mozilla.org/show_bug.cgi?id=534260 */ if (unlikely (bbox.origin.x == -32767 && bbox.origin.y == -32767 && bbox.size.width == 65534 && bbox.size.height == 65534)) { bbox.origin.x = bbox.origin.y = 0; bbox.size.width = bbox.size.height = 0; } bbox = CGRectMake (bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); /* Should we want to always integer-align glyph extents, we can do so in this way */ #if 0 { CGAffineTransform textMatrix; textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, 0.0f, 0.0f); bbox = CGRectApplyAffineTransform (bbox, textMatrix); bbox = CGRectIntegral (bbox); bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix)); } #endif #if 0 fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph, bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); #endif xmin = CGRectGetMinX(bbox); ymin = CGRectGetMinY(bbox); xmax = CGRectGetMaxX(bbox); ymax = CGRectGetMaxY(bbox); extents.x_bearing = xmin; extents.y_bearing = - ymax; extents.width = xmax - xmin; extents.height = ymax - ymin; extents.x_advance = (double) advance / emscale; extents.y_advance = 0.0; #if 0 fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph, extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance); #endif FAIL: _cairo_scaled_glyph_set_metrics (scaled_glyph, &font->base, &extents); return status; }
CGRect CGRectStackedWithinRectFromEdge(CGRect rect, CGSize size, int count, CGRectEdge edge, bool reverse) { int max_columns = floor(rect.size.width / size.width); int max_rows = floor(rect.size.height / size.height); if (edge == CGRectMinYEdge) { int current_row = floor(count / max_columns); int current_col = (count - 1) % max_columns; if (reverse) current_col = max_columns - (current_col + 1); if (current_col > max_columns || current_row > max_rows) { return CGRectNull; } else { CGFloat x = CGRectGetMinX(rect) + (current_col * size.width); CGFloat y = CGRectGetMinY(rect) + (current_row * size.height); return CGRectMake(x, y, size.width, size.height); } } else if (edge == CGRectMaxYEdge) { int current_row = floor(count / max_columns); int current_col = (count - 1) % max_columns; if (!reverse) current_col = max_columns - (current_col + 1); if (current_col > max_columns || current_row > max_rows) { return CGRectNull; } else { CGFloat x = CGRectGetMinX(rect) + (current_col * size.width); CGFloat y = CGRectGetMaxY(rect) - size.height - (current_row * size.height); return CGRectMake(x, y, size.width, size.height); } } else if (edge == CGRectMinXEdge) { int current_col = floor(count / max_columns); int current_row = (count - 1) % max_columns; if (!reverse) current_row = max_rows - (current_row + 1); if (current_col > max_columns || current_row > max_rows) { return CGRectNull; } else { CGFloat x = CGRectGetMinX(rect) + (current_col * size.width); CGFloat y = CGRectGetMinY(rect) + (current_row * size.height); return CGRectMake(x, y, size.width, size.height); } } else if (edge == CGRectMaxXEdge) { int current_col = floor(count / max_columns); int current_row = (count - 1) % max_columns; if (reverse) current_row = max_rows - (current_row + 1); if (current_col > max_columns || current_row > max_rows) { return CGRectNull; } else { CGFloat x = CGRectGetMaxX(rect) - size.width - (current_col * size.width); CGFloat y = CGRectGetMinY(rect) + current_row * size.height; return CGRectMake(x, y, size.width, size.height); } } return CGRectNull; }
CGPoint CGRectBottomLeftPoint(CGRect rect) { return CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect)); }
static cairo_int_status_t _cairo_quartz_init_glyph_metrics (cairo_quartz_scaled_font_t *font, cairo_scaled_glyph_t *scaled_glyph) { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_quartz_font_face_t *font_face = _cairo_quartz_scaled_to_face(font); cairo_text_extents_t extents = {0, 0, 0, 0, 0, 0}; CGAffineTransform textMatrix; CGGlyph glyph = _cairo_quartz_scaled_glyph_index (scaled_glyph); int advance; CGRect bbox; double emscale = CGFontGetUnitsPerEmPtr (font_face->cgFont); double xscale, yscale; double xmin, ymin, xmax, ymax; if (glyph == INVALID_GLYPH) goto FAIL; if (!CGFontGetGlyphAdvancesPtr (font_face->cgFont, &glyph, 1, &advance) || !CGFontGetGlyphBBoxesPtr (font_face->cgFont, &glyph, 1, &bbox)) goto FAIL; status = _cairo_matrix_compute_basis_scale_factors (&font->base.scale, &xscale, &yscale, 1); if (status) goto FAIL; bbox = CGRectMake (bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); /* Should we want to always integer-align glyph extents, we can do so in this way */ #if 0 { CGAffineTransform textMatrix; textMatrix = CGAffineTransformMake (font->base.scale.xx, -font->base.scale.yx, -font->base.scale.xy, font->base.scale.yy, 0.0f, 0.0f); bbox = CGRectApplyAffineTransform (bbox, textMatrix); bbox = CGRectIntegral (bbox); bbox = CGRectApplyAffineTransform (bbox, CGAffineTransformInvert (textMatrix)); } #endif #if 0 fprintf (stderr, "[0x%04x] bbox: %f %f %f %f\n", glyph, bbox.origin.x / emscale, bbox.origin.y / emscale, bbox.size.width / emscale, bbox.size.height / emscale); #endif xmin = CGRectGetMinX(bbox); ymin = CGRectGetMinY(bbox); xmax = CGRectGetMaxX(bbox); ymax = CGRectGetMaxY(bbox); extents.x_bearing = xmin; extents.y_bearing = - ymax; extents.width = xmax - xmin; extents.height = ymax - ymin; extents.x_advance = (double) advance / emscale; extents.y_advance = 0.0; #if 0 fprintf (stderr, "[0x%04x] extents: bearings: %f %f dim: %f %f adv: %f\n\n", glyph, extents.x_bearing, extents.y_bearing, extents.width, extents.height, extents.x_advance); #endif FAIL: _cairo_scaled_glyph_set_metrics (scaled_glyph, &font->base, &extents); return status; }