DRAW_TEST_F(CGContextFlush, FillFlushMultipleDrawingCounters, WhiteBackgroundTest<>) { CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); static int sDrawCount = 5; for (int i = 0; i < sDrawCount; ++i) { _CGContextPushBeginDraw(context); } CGContextSetRGBFillColor(context, 1, 0, 0, 1); CGContextFillRect(context, bounds); for (int i = 0; i < sDrawCount; ++i) { // Multiple flushes should work. CGContextFlush(context); } // Add some extra drawings CGContextClearRect(context, bounds); // We should still have red & clear should not of been executed. unsigned char* dataPtr = static_cast<unsigned char*>(CGBitmapContextGetData(context)); ASSERT_NE(dataPtr, nullptr); // Validate only the red fill rect is executed. EXPECT_EQ(dataPtr[0], 0x00); EXPECT_EQ(dataPtr[1], 0x00); EXPECT_EQ(dataPtr[2], 0xff); EXPECT_EQ(dataPtr[3], 0xff); for (int i = 0; i < 3; ++i) { // Multiple flushes should work. CGContextFlush(context); } // validate clear EXPECT_EQ(dataPtr[0], 0x00); EXPECT_EQ(dataPtr[1], 0x00); EXPECT_EQ(dataPtr[2], 0x00); EXPECT_EQ(dataPtr[3], 0x00); CGContextSetRGBStrokeColor(context, 0, 1, 0, 1); CGContextStrokeRect(context, CGRectMake(100, 100, 200, 300)); // Still should be clear. EXPECT_EQ(dataPtr[0], 0x00); EXPECT_EQ(dataPtr[1], 0x00); EXPECT_EQ(dataPtr[2], 0x00); EXPECT_EQ(dataPtr[3], 0x00); for (int i = 0; i < sDrawCount; ++i) { _CGContextPopEndDraw(context); } }
DRAW_TEST_F(CGContextFlush, FillFlush, WhiteBackgroundTest<>) { CGContextRef context = GetDrawingContext(); CGRect bounds = GetDrawingBounds(); _CGContextPushBeginDraw(context); CGContextSetRGBFillColor(context, 1, 0, 0, 1); CGContextFillRect(context, bounds); // Flush the red fill rect CGContextFlush(context); CGContextSetRGBFillColor(context, 0, 0, 1, 1); CGContextFillRect(context, CGRectMake(0, 0, 300, 300)); // We should still have red & blue rectangle should not show up. unsigned char* dataPtr = static_cast<unsigned char*>(CGBitmapContextGetData(context)); ASSERT_NE(dataPtr, nullptr); // Validate only the red fill rect is executed. EXPECT_EQ(dataPtr[0], 0x00); EXPECT_EQ(dataPtr[1], 0x00); EXPECT_EQ(dataPtr[2], 0xff); EXPECT_EQ(dataPtr[3], 0xff); CGContextFlush(context); // We should now see the blue fill rect EXPECT_EQ(dataPtr[0], 0xff); EXPECT_EQ(dataPtr[1], 0x00); EXPECT_EQ(dataPtr[2], 0x00); EXPECT_EQ(dataPtr[3], 0xff); // Add some extra drawings CGContextClearRect(context, CGRectMake(100, 100, 200, 300)); CGPoint center = _CGRectGetCenter(bounds); CGMutablePathRef concentricCirclesPath = CGPathCreateMutable(); CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 50, 50 }, center)); CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 100, 100 }, center)); CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 150, 150 }, center)); CGPathAddEllipseInRect(concentricCirclesPath, nullptr, _CGRectCenteredOnPoint({ 200, 200 }, center)); CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 0.5); CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0); CGContextAddPath(context, concentricCirclesPath); CGContextDrawPath(context, kCGPathFillStroke); CGPathRelease(concentricCirclesPath); _CGContextPopEndDraw(context); }
static void Quartz_Mode(int mode, NewDevDesc *dd) { QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific; if(mode == 0) CGContextFlush( GetContext(xd) ); }
/* draw image to frame */ static void icvDrawImage( CvWindow* window ) { Assert( window != 0 ); if( window->imageRef == 0 ) return; CGContextRef myContext; CvTrackbar* t; CGRect rect; Rect portrect; int width = window->imageWidth; int height = window->imageHeight; GetWindowPortBounds(window->window, &portrect); if( window->flags & CV_WINDOW_AUTOSIZE ) { CGPoint origin = {0,0}; CGSize size = {portrect.right-portrect.left, portrect.bottom-portrect.top-window->trackbarheight}; rect.origin = origin; rect.size = size; } else { CGPoint origin = {0, portrect.bottom - height - window->trackbarheight}; CGSize size = {width, height}; rect.origin = origin; rect.size = size; } /* To be sybnchronous we are using this, better would be to susbcribe to the draw event and process whenever requested, we might save SOME CPU cycles*/ SetPortWindowPort (window->window); QDBeginCGContext (GetWindowPort (window->window), &myContext); CGContextSetInterpolationQuality (myContext, kCGInterpolationLow); CGContextDrawImage(myContext,rect,window->imageRef); CGContextFlush(myContext);// 4 QDEndCGContext (GetWindowPort(window->window), &myContext);// 5 }
void MCStack::redrawicon() { // MW-2005-07-18: It is possible for this to be called if window == NULL in which // case bad things can happen - so don't let this occur. if (iconid != 0 && window != NULL) { MCImage *iptr = (MCImage *)getobjid(CT_IMAGE, iconid); if (iptr != NULL) { CGImageRef tdockimage; CGrafPtr tport; CGrafPtr curport; CGContextRef context; OSStatus theErr; CGRect cgrect = CGRectMake(0,0,128,128); GetPort( &curport); OSErr err = CreateQDContextForCollapsedWindowDockTile((WindowPtr)window->handle.window, &tport); if (err == noErr) { SetPort(tport); CreateCGContextForPort(tport, &context); tdockimage = iptr -> makeicon(128, 128); CGContextDrawImage(context,cgrect,tdockimage); if ( tdockimage ) CGImageRelease( tdockimage ); CGContextFlush(context); CGContextRelease(context); SetPort(curport); ReleaseQDContextForCollapsedWindowDockTile((WindowPtr)window->handle.window, tport); } } } }
void wxOverlayImpl::EndDrawing( wxDC* dc) { wxDCImpl *impl = dc->GetImpl(); wxGCDCImpl *win_impl = wxDynamicCast(impl,wxGCDCImpl); if (win_impl) win_impl->SetGraphicsContext(NULL); CGContextFlush( m_overlayContext ); }
// FIXME: Is it possible to merge getWindowsContext and createWindowsBitmap into a single API // suitable for all clients? HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { // FIXME: Should a bitmap be created also when a shadow is set? if (mayCreateBitmap && inTransparencyLayer()) { if (dstRect.isEmpty()) return 0; // Create a bitmap DC in which to draw. BITMAPINFO bitmapInfo; bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfo.bmiHeader.biWidth = dstRect.width(); bitmapInfo.bmiHeader.biHeight = dstRect.height(); bitmapInfo.bmiHeader.biPlanes = 1; bitmapInfo.bmiHeader.biBitCount = 32; bitmapInfo.bmiHeader.biCompression = BI_RGB; bitmapInfo.bmiHeader.biSizeImage = 0; bitmapInfo.bmiHeader.biXPelsPerMeter = 0; bitmapInfo.bmiHeader.biYPelsPerMeter = 0; bitmapInfo.bmiHeader.biClrUsed = 0; bitmapInfo.bmiHeader.biClrImportant = 0; void* pixels = 0; HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0); if (!bitmap) return 0; HDC bitmapDC = ::CreateCompatibleDC(m_data->m_hdc); ::SelectObject(bitmapDC, bitmap); // Fill our buffer with clear if we're going to alpha blend. if (supportAlphaBlend) { BITMAP bmpInfo; GetObject(bitmap, sizeof(bmpInfo), &bmpInfo); int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight; memset(bmpInfo.bmBits, 0, bufferSize); } // Make sure we can do world transforms. SetGraphicsMode(bitmapDC, GM_ADVANCED); // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap. XFORM xform; xform.eM11 = 1.0f; xform.eM12 = 0.0f; xform.eM21 = 0.0f; xform.eM22 = 1.0f; xform.eDx = -dstRect.x(); xform.eDy = -dstRect.y(); ::SetWorldTransform(bitmapDC, &xform); return bitmapDC; } CGContextFlush(platformContext()); m_data->save(); return m_data->m_hdc; }
PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const { if (m_context->isAcceleratedContext()) { CGContextFlush(context()->platformContext()); #if defined(BUILDING_ON_LION) m_data.m_lastFlushTime = currentTimeMS(); #endif } return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1); }
PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const { if (m_context->isAcceleratedContext()) { CGContextFlush(context()->platformContext()); #if defined(BUILDING_ON_LION) m_data.m_lastFlushTime = currentTimeMS(); #endif } return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false); }
void MacDock::overlay(const QString& text) { if (text.isEmpty()) { overlayed = false; RestoreApplicationDockTileImage(); return; } // Create the context CGContextRef context = BeginCGContextForApplicationDockTile(); if (!overlayed) { overlayed = true; // Add some subtle drop down shadow // FIXME: Disabled because 10.2 doesn't support it //CGSize s = { 2.0, -4.0 }; //CGContextSetShadow(context,s,5.0); } // Draw a circle CGContextBeginPath(context); CGContextAddArc(context, 95.0, 95.0, 25.0, 0.0, 2 * M_PI, true); CGContextClosePath(context); CGContextSetRGBFillColor(context, 1, 0.0, 0.0, 1); CGContextFillPath(context); // Set the clipping path to the same circle CGContextBeginPath(context); CGContextAddArc(context, 95.0, 95.0, 25.0, 0.0, 2 * M_PI, true); CGContextClip(context); // Remove drop shadow // FIXME: Disabled because 10.2 doesn't support it //CGSize s = { 0.0, -0.0 }; //CGContextSetShadowWithColor(context, s, 0, NULL); // Select the appropriate font CGContextSelectFont(context,DOCK_FONT_NAME, DOCK_FONT_SIZE, kCGEncodingMacRoman); CGContextSetRGBFillColor(context, 1, 1, 1, 1); // Draw the text invisible CGPoint begin = CGContextGetTextPosition(context); CGContextSetTextDrawingMode(context, kCGTextInvisible); CGContextShowTextAtPoint(context, begin.x, begin.y, text.toStdString().c_str(), text.length()); CGPoint end = CGContextGetTextPosition(context); // Draw the text CGContextSetTextDrawingMode(context, kCGTextFill); CGContextShowTextAtPoint(context, 95 - (end.x - begin.x)/2, 95 - 8, text.toStdString().c_str(), text.length()); // Cleanup CGContextFlush(context); EndCGContextForApplicationDockTile(context); }
static Rboolean Quartz_Locator(double *x, double *y, NewDevDesc *dd) { EventRecord event; SInt16 key; Boolean gotEvent; Boolean mouseClick = false; Point myPoint; WindowPtr window; SInt16 partCode; GrafPtr savePort; Cursor arrow ; QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific; int useBeep = asLogical(GetOption(install("locatorBell"), R_NilValue)); GetPort(&savePort); SetPortWindowPort(xd->window); SetThemeCursor(kThemeCrossCursor); while(!mouseClick) { gotEvent = WaitNextEvent( everyEvent, &event, 0, nil); CGContextFlush( GetContext(xd) ); if (event.what == mouseDown) { partCode = FindWindow(event.where, &window); if ((window == (xd->window)) && (partCode == inContent)) { myPoint = event.where; GlobalToLocal(&myPoint); *x = (double)(myPoint.h); *y = (double)(myPoint.v); if(useBeep) SysBeep(1); mouseClick = true; } } if (event.what == keyDown) { key = (event.message & charCodeMask); if (key == 0x1b){ /* exits when the esc key is pressed */ SetPort(savePort); SetThemeCursor(kThemeIBeamCursor); return FALSE; } } } SetPort(savePort); SetThemeCursor(kThemeIBeamCursor); return TRUE; }
static OSStatus DrawWindow( WindowRef windowRef ) { OSStatus err = noErr; DrawContextStruct *context; // get the context from windowRef context = (DrawContextStruct *) GetWRefCon( windowRef ); // skip any drawing if the context has not yet been initialized if ( context->cgContext == NULL ) return err; // we only need to do this if there are characters in the buffer. If there // aren't any characters, then there's nothing to draw. if ( context->characterCount > 0 ) { // if there isn't a layout object, then we need to add one to the // context if ( context->layoutObject == NULL ) { err = AddNewTextLayoutToContext( context ); require_noerr( err, DrawContext_err ); } // based on the current options selection, either just draw a single // line, or do the fancy glyph rotate stuff. switch ( gOptionsMenuSelection ) { case kOptionsMenuTextBurst: err = DrawGlyphBurst( context ); require_noerr( err, DrawContext_err ); break; case kOptionsMenuItemNone: default: err = DrawSingleLine( context ); require_noerr( err, DrawContext_err ); break; } // flush the CGContext CGContextFlush( context->cgContext ); } DrawContext_err: return err; }
void PoofItGood( Point centerPt ) { CGRect box; WindowRef window; Rect bounds; CGContextRef context; CGImageRef image; float windowWidth; float windowHeight; int i; image = GetThePoofImage(); if ( image == NULL ) goto Bail; windowWidth = CGImageGetWidth( image ) / NUMBER_OF_POOF_ANIM_FRAMES; windowHeight = CGImageGetHeight( image ); // Start our animation bounds at the first item in the animation strip box.origin.x = box.origin.y = 0; box.size.width = CGImageGetWidth( image ); box.size.height = CGImageGetHeight( image ); bounds.top = centerPt.v - (SInt16)(windowHeight / 2); bounds.left = centerPt.h - (SInt16)(windowWidth / 2); bounds.bottom = bounds.top + (SInt16)windowHeight; bounds.right = bounds.left + (SInt16)windowWidth; CreateNewWindow( kOverlayWindowClass, 0, &bounds, &window ); CreateCGContextForPort( GetWindowPort( window ), &context ); ShowWindow( window ); for ( i = 1; i <= NUMBER_OF_POOF_ANIM_FRAMES; i++ ) { CGContextClearRect( context, box ); CGContextDrawImage( context, box, image ); CGContextFlush( context ); Delay( EventTimeToTicks( POOF_ANIMATION_DELAY ), NULL ); box.origin.x -= windowWidth; } CGContextRelease( context ); CGImageRelease( image ); DisposeWindow( window ); Bail: return; }
static void flushproc(void *a) { for(;;) { if(needflush) { drawqlock(); QDBeginCGContext(GetWindowPort(theWindow), &context); CGContextFlush(context); QDEndCGContext(GetWindowPort(theWindow), &context); needflush = false; drawqunlock(); } usleep(33333); } }
GraphicsContext* ImageBuffer::context() const { #if defined(BUILDING_ON_LION) // Force a flush if last flush was more than 20ms ago if (m_context->isAcceleratedContext()) { double elapsedTime = currentTimeMS() - m_data.m_lastFlushTime; double maxFlushInterval = 20; // in ms if (elapsedTime > maxFlushInterval) { CGContextRef context = m_context->platformContext(); CGContextFlush(context); m_data.m_lastFlushTime = currentTimeMS(); } } #endif return m_context.get(); }
static void Quartz_NewPage(R_GE_gcontext *gc, NewDevDesc *dd) { QuartzDesc *xd = (QuartzDesc*)dd->deviceSpecific; CGPoint origin = {0.0, 0.0}; CGSize size; CGRect area; size.width = xd->windowWidth; size.height = xd->windowHeight; area.origin = origin; area.size = size; Quartz_Clip(0,size.width, 0, size.height, dd); /* * Paul to Stefano: * Not sure what is intended here: looks like you are * making sure that on a "new page" operation you clear * the window -- filling the window with a "missing" * colour wouldn't do the job so you use "white". * We no longer deal with NA as a colour internally so * I have changed this as follows: * (i) if gc->fill is not opaque, then fill with white * (to clear the window) * (ii) fill with gc->fill * (to produce the specified "background" which may or * may not be transparent) */ if (!R_OPAQUE(gc->fill)) { unsigned int tempcol = gc->fill; gc->fill = R_RGB(255, 255, 255); Quartz_SetFill(gc->fill, gc->gamma, dd); CGContextFillRect( GetContext(xd), area); gc->fill = tempcol; } Quartz_SetFill(gc->fill, gc->gamma, dd); CGContextFillRect( GetContext(xd), area); CGContextFlush( GetContext(xd) ); /* we need to flash it just now */ }
void QMacWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset) { Q_UNUSED(offset); // Get a context for the widget. #ifndef QT_MAC_USE_COCOA CGContextRef context; CGrafPtr port = GetWindowPort(qt_mac_window_for(widget)); QDBeginCGContext(port, &context); #else extern CGContextRef qt_mac_graphicsContextFor(QWidget *); CGContextRef context = qt_mac_graphicsContextFor(widget); #endif CGContextRetain(context); CGContextSaveGState(context); // Flip context. CGContextTranslateCTM(context, 0, widget->height()); CGContextScaleCTM(context, 1, -1); // Clip to region. const QVector<QRect> &rects = rgn.rects(); for (int i = 0; i < rects.size(); ++i) { const QRect &rect = rects.at(i); CGContextAddRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height())); } CGContextClip(context); // Draw the image onto the window. const CGRect dest = CGRectMake(0, 0, widget->width(), widget->height()); const CGImageRef image = d_ptr->device.toMacCGImageRef(); qt_mac_drawCGImage(context, &dest, image); CFRelease(image); // Restore context. CGContextRestoreGState(context); #ifndef QT_MAC_USE_COCOA QDEndCGContext(port, &context); #else CGContextFlush(context); #endif CGContextRelease(context); }
static pascal OSStatus OverlayWindowEventHandlerProc( EventHandlerCallRef inCallRef, EventRef inEvent, void* inUserData ) { #pragma unused( inCallRef ) Rect windowRect; CGRect box; CGContextRef cgContext; UInt32 eventKind = GetEventKind( inEvent ); UInt32 eventClass = GetEventClass( inEvent ); OSStatus err = eventNotHandledErr; WindowStorage *windowStorage = (WindowStorage*) inUserData; switch ( eventClass ) { case kEventClassWindow: if ( eventKind == kEventWindowClose ) { windowStorage->overlayWindow = NULL; // Let the default handler DisposeWindow() for us, just set our WindowRef to NULL } else if ( (eventKind == kEventWindowBoundsChanged) || (eventKind == kEventWindowShown) ) // Draw the overlay window { GetWindowPortBounds( windowStorage->overlayWindow, &windowRect ); //box.origin.x = box.origin.y = 0; //box.size.width = windowRect.right - windowRect.left; //box.size.height = windowRect.bottom - windowRect.top; box = CGRectMake( 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top ); QDBeginCGContext( GetWindowPort(windowStorage->overlayWindow), &cgContext ); CGContextClearRect( cgContext, box ); // Paint a semi-transparent box in the middle of our window box.origin.x = (windowRect.right - windowRect.left) / 4; box.size.width = (windowRect.right - windowRect.left) / 2; CGContextSetRGBFillColor( cgContext, 0.5, 0.75, 0.75, 0.2 ); CGContextFillRect( cgContext, box ); CGContextFlush( cgContext ); QDEndCGContext( GetWindowPort(windowStorage->overlayWindow), &cgContext ); } break; } return( err ); }
OpBitmap* CreateOpBitmapFromIcon(IconRef iconin, int cx, int cy) { if (iconin) { OpBitmap* bm; if (OpStatus::IsSuccess(OpBitmap::Create(&bm, cx, cy, FALSE, TRUE, 0, 0, TRUE))) { CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); void* p = bm->GetPointer(OpBitmap::ACCESS_WRITEONLY); memset(p, 0, bm->Height()*bm->GetBytesPerLine()); CGBitmapInfo alpha = kCGBitmapByteOrderVegaInternal; CGContextRef ctx = CGBitmapContextCreate(p, bm->Width(), bm->Height(), 8, bm->GetBytesPerLine(), colorSpace, alpha); CGColorSpaceRelease(colorSpace); CGRect cgrect = CGRectMake(0,0,cx,cy); PlotIconRefInContext(ctx, &cgrect, kAlignAbsoluteCenter, kTransformNone, NULL, kPlotIconRefNormalFlags, iconin); CGContextFlush(ctx); CGContextRelease(ctx); bm->ReleasePointer(); return bm; } } return NULL; }
PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const { if (m_context->isAcceleratedContext()) CGContextFlush(context()->platformContext()); return m_data.getData(rect, m_size, m_context->isAcceleratedContext(), false); }
void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { if (m_context->isAcceleratedContext()) CGContextFlush(context()->platformContext()); m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), false); }
// This example is almost identical to the helloworld example, except that // in this case, there are two styles instead of just one. ATSUSetRunStyle // is used to apply a style to different parts of the text. // void DrawMultipleStylesContents(WindowRef window) { CFStringRef string; UniChar *text; UniCharCount length; UniCharArrayOffset currentStart, currentEnd; ATSUStyle style1, style2; ATSUTextLayout layout; ATSUFontID font; Fixed pointSize; ATSUAttributeTag tags[2]; ByteCount sizes[2]; ATSUAttributeValuePtr values[2]; Fixed lineWidth, ascent, descent; CGContextRef cgContext; float x, y, cgY, windowHeight; ItemCount numSoftBreaks; UniCharArrayOffset *theSoftBreaks; int i; GrafPtr port, savedPort; Rect portBounds; // Set up the graphics port port = GetWindowPort(window); GetPort(&savedPort); SetPort(port); GetPortBounds(port, &portBounds); EraseRect(&portBounds); // Create a style object. This is one of two objects necessary to draw using ATSUI. // (The layout is the other.) verify_noerr( ATSUCreateStyle(&style1) ); // Look up the font we are going to use, and set it in the style object, using // the aforementioned "triple" (tag, size, value) semantics. This is how almost // all settings in ATSUI are applied. verify_noerr( ATSUFindFontFromName(kMultipleStylesFontName, strlen(kMultipleStylesFontName), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &font) ); tags[0] = kATSUFontTag; sizes[0] = sizeof(ATSUFontID); values[0] = &font; verify_noerr( ATSUSetAttributes(style1, 1, tags, sizes, values) ); // Set the point size, also using a triple. You can actually set multiple triples at once, // since the tag, size, and value parameters are arrays. Other examples do this, such as // the vertical text example. // pointSize = Long2Fix(kMultipleStylesFontSize); tags[0] = kATSUSizeTag; sizes[0] = sizeof(Fixed); values[0] = &pointSize; verify_noerr( ATSUSetAttributes(style1, 1, tags, sizes, values) ); // Now we create the second of two objects necessary to draw text using ATSUI, the layout. // You can specify a pointer to the text buffer at layout creation time, or later using // the routine ATSUSetTextPointerLocation(). Below, we do it after layout creation time. verify_noerr( ATSUCreateTextLayout(&layout) ); // Before assigning text to the layout, we must first convert the string we plan to draw // from a CFStringRef into an array of UniChar. string = CFStringCreateWithCString(NULL, "In this example, various parts of the text have different styles applied. The same style is used more than once.", kCFStringEncodingASCII); // Extract the raw Unicode from the CFString, then dispose of the CFString length = CFStringGetLength(string); text = (UniChar *)malloc(length * sizeof(UniChar)); CFStringGetCharacters(string, CFRangeMake(0, length), text); CFRelease(string); // Attach the resulting UTF-16 Unicode text to the layout verify_noerr( ATSUSetTextPointerLocation(layout, text, kATSUFromTextBeginning, kATSUToTextEnd, length) ); // Now we tie the two necessary objects, the layout and the style, together verify_noerr( ATSUSetRunStyle(layout, style1, kATSUFromTextBeginning, kATSUToTextEnd) ); // Now, for this example we create a second style, and assign it to various runs within // the text. For our example, the run offsets are hard-coded for simplicity's sake. In // a real application, style runs are often assigned from external sources, such as user // selection. verify_noerr( ATSUCreateAndCopyStyle(style1, &style2) ); // Change the font for the second style verify_noerr( ATSUFindFontFromName(kMultipleStylesFontName2, strlen(kMultipleStylesFontName2), kFontFullName, kFontNoPlatform, kFontNoScript, kFontNoLanguage, &font) ); tags[0] = kATSUFontTag; sizes[0] = sizeof(ATSUFontID); values[0] = &font; verify_noerr( ATSUSetAttributes(style2, 1, tags, sizes, values) ); // Apply the new style to the text in various places verify_noerr( ATSUSetRunStyle(layout, style2, 8, 7) ); // The word "example" verify_noerr( ATSUSetRunStyle(layout, style2, 65, 7) ); // The word "applied" verify_noerr( ATSUSetRunStyle(layout, style2, 83, 5) ); // The word "style" verify_noerr( ATSUSetRunStyle(layout, style2, 107, 4) ); // The word "once" // In this example, we are breaking text into lines. // Therefore, we need to know the width of the line. lineWidth = X2Fix(portBounds.right - portBounds.left - 2.0*kMultipleStylesMargin); tags[0] = kATSULineWidthTag; sizes[0] = sizeof(Fixed); values[0] = &lineWidth; verify_noerr( ATSUSetLayoutControls(layout, 1, tags, sizes, values) ); // Prepare the CGContext for drawing QDBeginCGContext(port, &cgContext); tags[0] = kATSUCGContextTag; sizes[0] = sizeof(CGContextRef); values[0] = &cgContext; verify_noerr( ATSUSetLayoutControls(layout, 1, tags, sizes, values) ); // Prepare the coordinates for drawing. In our example, "x" and "y" are the coordinates // in QD space. "cgY" contains the y coordinate in CG space. // windowHeight = portBounds.bottom - portBounds.top; x = kMultipleStylesMargin; // leave a small left margin y = kMultipleStylesMargin; // leave a small top margin cgY = windowHeight - y; // Subtract the y coordinate from the height of the // window to get the coordinate in CG-aware space. // Break the text into lines verify_noerr( ATSUBatchBreakLines(layout, kATSUFromTextBeginning, length, lineWidth, &numSoftBreaks) ); verify_noerr( ATSUGetSoftLineBreaks(layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, NULL, &numSoftBreaks) ); theSoftBreaks = (UniCharArrayOffset *) malloc(numSoftBreaks * sizeof(UniCharArrayOffset)); verify_noerr( ATSUGetSoftLineBreaks(layout, kATSUFromTextBeginning, kATSUToTextEnd, numSoftBreaks, theSoftBreaks, &numSoftBreaks) ); // Loop over all the lines and draw them currentStart = 0; for (i=0; i <= numSoftBreaks; i++) { currentEnd = ((numSoftBreaks > 0 ) && (numSoftBreaks > i)) ? theSoftBreaks[i] : length; // This is the height of a line, the ascent and descent. Getting the values this way is the preferred method. ATSUGetLineControl(layout, currentStart, kATSULineAscentTag, sizeof(ATSUTextMeasurement), &ascent, NULL); ATSUGetLineControl(layout, currentStart, kATSULineDescentTag, sizeof(ATSUTextMeasurement), &descent, NULL); // Make room for the area above the baseline y += Fix2X(ascent); cgY = windowHeight - y; // Draw the text verify_noerr( ATSUDrawText(layout, currentStart, currentEnd - currentStart, X2Fix(x), X2Fix(cgY)) ); // Make room for the area beloww the baseline y += Fix2X(descent); // Prepare for next line currentStart = currentEnd; } // This is a one-shot window, so we are now ready to dispose of all our objects. // Normally, we would want to keep everything around in case we needed to redraw or change // the text at some point. // Tear down the CGContext CGContextFlush(cgContext); QDEndCGContext(port, &cgContext); // Deallocate string storage free(text); // Layout and styles also need to be disposed verify_noerr( ATSUDisposeStyle(style1) ); verify_noerr( ATSUDisposeStyle(style2) ); verify_noerr( ATSUDisposeTextLayout(layout) ); // Restore the graphics port SetPort(savedPort); }
void QuartzWindow::post_draw(bool incremental) { CGContextFlush(myContext); }
static bool font_renderer_create_atlas(CTFontRef face, ct_font_renderer_t *handle) { int max_width, max_height; unsigned i; size_t bytesPerRow; CGGlyph glyphs[CT_ATLAS_SIZE]; CGRect bounds[CT_ATLAS_SIZE]; CGSize advances[CT_ATLAS_SIZE]; float ascent, descent; CGContextRef offscreen; CFDictionaryRef attr; CFTypeRef values[1]; CFStringRef keys[1]; void *bitmapData = NULL; bool ret = true; size_t bitsPerComponent = 8; UniChar characters[CT_ATLAS_SIZE] = {0}; values[0] = face; keys[0] = kCTFontAttributeName; for (i = 0; i < CT_ATLAS_SIZE; i++) characters[i] = (UniChar)i; CTFontGetGlyphsForCharacters(face, characters, glyphs, CT_ATLAS_SIZE); CTFontGetBoundingRectsForGlyphs(face, #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 kCTFontOrientationDefault, #else kCTFontDefaultOrientation, #endif glyphs, bounds, CT_ATLAS_SIZE); CTFontGetAdvancesForGlyphs(face, #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 kCTFontOrientationDefault, #else kCTFontDefaultOrientation, #endif glyphs, advances, CT_ATLAS_SIZE); ascent = CTFontGetAscent(face); descent = CTFontGetDescent(face); max_width = 0; max_height = 0; for (i = 0; i < CT_ATLAS_SIZE; i++) { int origin_x, origin_y; struct font_glyph *glyph = &handle->glyphs[i]; if (!glyph) continue; origin_x = ceil(bounds[i].origin.x); origin_y = ceil(bounds[i].origin.y); glyph->draw_offset_x = 0; glyph->draw_offset_y = -ascent; glyph->width = ceil(bounds[i].size.width); glyph->height = ceil(bounds[i].size.height); glyph->advance_x = ceil(advances[i].width); glyph->advance_y = ceil(advances[i].height); max_width = MAX(max_width, (origin_x + glyph->width)); max_height = MAX(max_height, (origin_y + glyph->height)); } max_height = MAX(max_height, ceil(ascent+descent)); handle->atlas.width = max_width * CT_ATLAS_COLS; handle->atlas.height = max_height * CT_ATLAS_ROWS; handle->atlas.buffer = (uint8_t*) calloc(handle->atlas.width * handle->atlas.height, 1); if (!handle->atlas.buffer) { ret = false; goto end; } bytesPerRow = max_width; bitmapData = calloc(max_height, bytesPerRow); offscreen = CGBitmapContextCreate(bitmapData, max_width, max_height, bitsPerComponent, bytesPerRow, NULL, kCGImageAlphaOnly); CGContextSetTextMatrix(offscreen, CGAffineTransformIdentity); attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); for (i = 0; i < CT_ATLAS_SIZE; i++) { char glyph_cstr[2]; const uint8_t *src; uint8_t *dst; unsigned offset_x, offset_y, r, c; CFStringRef glyph_cfstr; CFAttributedStringRef attrString; CTLineRef line; struct font_glyph *glyph = &handle->glyphs[i]; if (!glyph) continue; glyph->width = max_width; glyph->height = max_height; offset_x = (i % CT_ATLAS_COLS) * max_width; offset_y = (i / CT_ATLAS_COLS) * max_height; glyph->atlas_offset_x = offset_x; glyph->atlas_offset_y = offset_y; glyph_cstr[0] = i; glyph_cstr[1] = 0; glyph_cfstr = CFStringCreateWithCString( NULL, glyph_cstr, kCFStringEncodingASCII ); attrString = CFAttributedStringCreate(NULL, glyph_cfstr, attr); CFRelease(glyph_cfstr); glyph_cfstr = NULL; line = CTLineCreateWithAttributedString(attrString); CFRelease(attrString); attrString = NULL; memset( bitmapData, 0, max_height * bytesPerRow ); CGContextSetTextPosition(offscreen, 0, descent); CTLineDraw(line, offscreen); CGContextFlush( offscreen ); CFRelease( line ); line = NULL; dst = (uint8_t*)handle->atlas.buffer; src = (const uint8_t*)bitmapData; for (r = 0; r < max_height; r++ ) { for (c = 0; c < max_width; c++) { unsigned src_idx = r * bytesPerRow + c; unsigned dest_idx = (r + offset_y) * (CT_ATLAS_COLS * max_width) + (c + offset_x); uint8_t v = src[src_idx]; dst[dest_idx] = v; } } } CFRelease(attr); CGContextRelease(offscreen); attr = NULL; offscreen = NULL; free(bitmapData); end: return ret; }
void ImageBuffer::flushContext() const { CGContextFlush(context().platformContext()); }
void wxGCDC::Flush() { #ifdef __WXMAC__ CGContextFlush( (CGContextRef) m_graphicContext->GetNativeContext() ); #endif }
void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { if (m_accelerateRendering) CGContextFlush(context()->platformContext()); putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size, m_accelerateRendering); }
void wxOverlayImpl::EndDrawing( wxWindowDC* dc) { dc->SetGraphicsContext(NULL); CGContextFlush( m_overlayContext ); }
PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const { if (m_accelerateRendering) CGContextFlush(context()->platformContext()); return getImageData<Premultiplied>(rect, m_data, m_size, m_accelerateRendering); }
void GraphicsContextPlatformPrivate::flush() { CGContextFlush(m_cgContext.get()); }