static
OSStatus DrawGlyphBurst(
	DrawContextStruct 	*context )
{
	OSStatus				err;
	ATSUTextMeasurement		xPosition;
	ATSUTextMeasurement		yPosition;
	Fixed					numDegreesPerLine;
	Fixed					currentDegree;
	ATSUAttributeTag		tag = kATSULineRotationTag;
	ByteCount				valueSize = sizeof( Fixed );
	ATSUAttributeValuePtr	valuePtr = &currentDegree;
	
	// initialize the current degree to 360 degrees
	currentDegree = (360 << 16);
	
	// calculate the number of degrees for each glyph burst
	numDegreesPerLine = currentDegree / kGlyphBurstLines;
	
	// set the xPosition and the yPosition at the center of the window
	xPosition = ( context->bounds.size.width / 2 );
	yPosition = ( context->bounds.size.height / 2 );
		
	xPosition = xPosition << 16;
	yPosition = yPosition << 16;
	
	// loop through until all lines are drawn
	while ( currentDegree > 0 )
	{
		// set the current rotation degree in the text layout object
		err = ATSUSetLayoutControls( context->layoutObject, 1, &tag, &valueSize, &valuePtr );
		require_noerr( err, DrawGlyphBurst_err );
		
		// draw!
		err = ATSUDrawText( context->layoutObject, kATSUFromTextBeginning, kATSUToTextEnd, xPosition, yPosition );
			
		// decrement the current degree
		currentDegree -= numDegreesPerLine;
	}
	
	// set the current degree back to zero, in case it wasn't
	currentDegree = 0;
	err = ATSUSetLayoutControls( context->layoutObject, 1, &tag, &valueSize, &valuePtr );
	require_noerr( err, DrawGlyphBurst_err );	
		
DrawGlyphBurst_err:
		
	return err;	

}
Esempio n. 2
0
static bool osx_draw_text_substring_to_cgcontext_at_location(uindex_t p_length, CGContextRef p_cgcontext, MCGPoint p_location)
{
	if (s_layout == NULL || s_style == NULL)
		return false;
	
    OSStatus t_err;
	t_err = noErr;
	
	ATSUAttributeTag t_layout_tags[] =
	{
		kATSUCGContextTag,
	};
	ByteCount t_layout_sizes[] =
	{
		sizeof(CGContextRef),
	};
	ATSUAttributeValuePtr t_layout_attrs[] =
	{
		&p_cgcontext,
	};

	if (t_err == noErr)
		t_err = ATSUSetLayoutControls(s_layout, sizeof(t_layout_tags) / sizeof(ATSUAttributeTag), t_layout_tags, t_layout_sizes, t_layout_attrs);
	
    if (t_err == noErr)
        t_err = ATSUDrawText(s_layout, 0, p_length / 2, ((int32_t)p_location . x) << 16, ((int32_t)p_location . y) << 16);
    
    return t_err == noErr;
}
Esempio n. 3
0
static void
InitializeLayout()
{
	OSStatus	status = ATSUCreateTextLayout(&sTextLayout);
	ATSUFontFallbacks fallbacks;
	status = ATSUCreateFontFallbacks(&fallbacks);
	status = ATSUSetObjFontFallbacks(fallbacks, 0, 0, kATSULastResortOnlyFallback);
	ATSUAttributeTag		tag = kATSULineFontFallbacksTag;
	ByteCount				valueSize = sizeof(fallbacks);
	ATSUAttributeValuePtr	value = &fallbacks;
	status = ATSUSetLayoutControls(sTextLayout, 1, &tag, &valueSize, &value);
	status = ATSUSetTransientFontMatching(sTextLayout, true);
}
Esempio n. 4
0
// 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);
}
Esempio n. 5
0
PlatformFont::CharInfo& MacCarbFont::getCharInfo(const UTF16 ch) const
{
   // We use some static data here to avoid re allocating the same variable in a loop.
   // this func is primarily called by GFont::loadCharInfo(),
   Rect                 imageRect;
   CGContextRef         imageCtx;
   U32                  bitmapDataSize;
   ATSUTextMeasurement  tbefore, tafter, tascent, tdescent;
   OSStatus             err;

   // 16 bit character buffer for the ATUSI calls.
   // -- hey... could we cache this at the class level, set style and loc *once*, 
   //    then just write to this buffer and clear the layout cache, to speed up drawing?
   static UniChar chUniChar[1];
   chUniChar[0] = ch;

   // Declare and clear out the CharInfo that will be returned.
   static PlatformFont::CharInfo c;
   dMemset(&c, 0, sizeof(c));
   
   // prep values for GFont::addBitmap()
   c.bitmapIndex = 0;
   c.xOffset = 0;
   c.yOffset = 0;

   // put the text in the layout.
   // we've hardcoded a string length of 1 here, but this could work for longer strings... (hint hint)
   // note: ATSUSetTextPointerLocation() also clears the previous cached layout information.
   ATSUSetTextPointerLocation( mLayout, chUniChar, 0, 1, 1);
   ATSUSetRunStyle( mLayout, mStyle, 0,1);
   
   // get the typographic bounds. this tells us how characters are placed relative to other characters.
   ATSUGetUnjustifiedBounds( mLayout, 0, 1, &tbefore, &tafter, &tascent, &tdescent);
   c.xIncrement =  FixedToInt(tafter);
   
   // find out how big of a bitmap we'll need.
   // as a bonus, we also get the origin where we should draw, encoded in the Rect.
   ATSUMeasureTextImage( mLayout, 0, 1, 0, 0, &imageRect);
   U32 xFudge = 2;
   U32 yFudge = 1;
   c.width  = imageRect.right - imageRect.left + xFudge; // add 2 because small fonts don't always have enough room
   c.height = imageRect.bottom - imageRect.top + yFudge;
   c.xOrigin = imageRect.left; // dist x0 -> center line
   c.yOrigin = -imageRect.top; // dist y0 -> base line
   
   // kick out early if the character is undrawable
   if( c.width == xFudge || c.height == yFudge)
      return c;
   
   // allocate a greyscale bitmap and clear it.
   bitmapDataSize = c.width * c.height;
   c.bitmapData = new U8[bitmapDataSize];
   dMemset(c.bitmapData,0x00,bitmapDataSize);
   
   // get a graphics context on the bitmap
   imageCtx = CGBitmapContextCreate( c.bitmapData, c.width, c.height, 8, c.width, mColorSpace, kCGImageAlphaNone);
   if(!imageCtx) {
      Con::errorf("Error: failed to create a graphics context on the CharInfo bitmap! Drawing a blank block.");
      c.xIncrement = c.width;
      dMemset(c.bitmapData,0x0F,bitmapDataSize);
      return c;
   }

   // Turn off antialiasing for monospaced console fonts. yes, this is cheating.
   if(mSize < 12  && ( dStrstr(mName,"Monaco")!=NULL || dStrstr(mName,"Courier")!=NULL ))
      CGContextSetShouldAntialias(imageCtx, false);

   // Set up drawing options for the context.
   // Since we're not going straight to the screen, we need to adjust accordingly
   CGContextSetShouldSmoothFonts(imageCtx, false);
   CGContextSetRenderingIntent(imageCtx, kCGRenderingIntentAbsoluteColorimetric);
   CGContextSetInterpolationQuality( imageCtx, kCGInterpolationNone);
   CGContextSetGrayFillColor( imageCtx, 1.0, 1.0);
   CGContextSetTextDrawingMode( imageCtx,  kCGTextFill);
   
   // tell ATSUI to substitute fonts as needed for missing glyphs
   ATSUSetTransientFontMatching(mLayout, true); 

   // set up three parrallel arrays for setting up attributes. 
   // this is how most options in ATSUI are set, by passing arrays of options.
   ATSUAttributeTag theTags[] = { kATSUCGContextTag };
   ByteCount theSizes[] = { sizeof(CGContextRef) };
   ATSUAttributeValuePtr theValues[] = { &imageCtx };
   
   // bind the layout to the context.
   ATSUSetLayoutControls( mLayout, 1, theTags, theSizes, theValues );

   // Draw the character!
   int yoff = c.height < 3 ? 1 : 0; // kludge for 1 pixel high characters, such as '-' and '_'
   int xoff = 1;
   err = ATSUDrawText( mLayout, 0, 1, IntToFixed(-imageRect.left + xoff), IntToFixed(imageRect.bottom + yoff ) );
   CGContextRelease(imageCtx);
   
   if(err != noErr) {
      Con::errorf("Error: could not draw the character! Drawing a blank box.");
      dMemset(c.bitmapData,0x0F,bitmapDataSize);
   }


#if TORQUE_DEBUG
//   Con::printf("Font Metrics: Rect = %2i %2i %2i %2i  Char= %C, 0x%x  Size= %i, Baseline= %i, Height= %i",imageRect.top, imageRect.bottom, imageRect.left, imageRect.right,ch,ch, mSize,mBaseline, mHeight);
//   Con::printf("Font Bounds:  left= %2i right= %2i  Char= %C, 0x%x  Size= %i",FixedToInt(tbefore), FixedToInt(tafter), ch,ch, mSize);
#endif
      
   return c;
}
Esempio n. 6
0
void drawPlugin(NPP instance, NPCocoaEvent* event)
{
  if (!browserUAString)
    return;

  PluginInstance* currentInstance = (PluginInstance*)(instance->pdata);
  CGContextRef cgContext = event->data.draw.context;
  if (!cgContext)
    return;

  float windowWidth = currentInstance->window.width;
  float windowHeight = currentInstance->window.height;
  
  // save the cgcontext gstate
  CGContextSaveGState(cgContext);
  
  // we get a flipped context
  CGContextTranslateCTM(cgContext, 0.0, windowHeight);
  CGContextScaleCTM(cgContext, 1.0, -1.0);
  
  // draw a gray background for the plugin
  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
  CGContextSetGrayFillColor(cgContext, 0.5, 1.0);
  CGContextDrawPath(cgContext, kCGPathFill);
  
  // draw a black frame around the plugin
  CGContextAddRect(cgContext, CGRectMake(0, 0, windowWidth, windowHeight));
  CGContextSetGrayStrokeColor(cgContext, 0.0, 1.0);
  CGContextSetLineWidth(cgContext, 6.0);
  CGContextStrokePath(cgContext);
  
  // draw the UA string using ATSUI
  CGContextSetGrayFillColor(cgContext, 0.0, 1.0);
  ATSUStyle atsuStyle;
  ATSUCreateStyle(&atsuStyle);
  CFIndex stringLength = CFStringGetLength(browserUAString);
  UniChar* unicharBuffer = (UniChar*)malloc((stringLength + 1) * sizeof(UniChar));
  CFStringGetCharacters(browserUAString, CFRangeMake(0, stringLength), unicharBuffer);
  UniCharCount runLengths = kATSUToTextEnd;
  ATSUTextLayout atsuLayout;
  ATSUCreateTextLayoutWithTextPtr(unicharBuffer,
                                  kATSUFromTextBeginning,
                                  kATSUToTextEnd,
                                  stringLength,
                                  1,
                                  &runLengths,
                                  &atsuStyle,
                                  &atsuLayout);
  ATSUAttributeTag contextTag = kATSUCGContextTag;
  ByteCount byteSize = sizeof(CGContextRef);
  ATSUAttributeValuePtr contextATSUPtr = &cgContext;
  ATSUSetLayoutControls(atsuLayout, 1, &contextTag, &byteSize, &contextATSUPtr);
  ATSUTextMeasurement lineAscent, lineDescent;
  ATSUGetLineControl(atsuLayout,
                    kATSUFromTextBeginning,
                    kATSULineAscentTag,
                    sizeof(ATSUTextMeasurement),
                    &lineAscent,
                    &byteSize);
  ATSUGetLineControl(atsuLayout,
                    kATSUFromTextBeginning,
                    kATSULineDescentTag,
                    sizeof(ATSUTextMeasurement),
                    &lineDescent,
                    &byteSize);
  float lineHeight = FixedToFloat(lineAscent) + FixedToFloat(lineDescent);  
  ItemCount softBreakCount;
  ATSUBatchBreakLines(atsuLayout,
                      kATSUFromTextBeginning,
                      stringLength,
                      FloatToFixed(windowWidth - 10.0),
                      &softBreakCount);
  ATSUGetSoftLineBreaks(atsuLayout,
                        kATSUFromTextBeginning,
                        kATSUToTextEnd,
                        0, NULL, &softBreakCount);
  UniCharArrayOffset* softBreaks = (UniCharArrayOffset*)malloc(softBreakCount * sizeof(UniCharArrayOffset));
  ATSUGetSoftLineBreaks(atsuLayout,
                        kATSUFromTextBeginning,
                        kATSUToTextEnd,
                        softBreakCount, softBreaks, &softBreakCount);
  UniCharArrayOffset currentDrawOffset = kATSUFromTextBeginning;
  int i = 0;
  while (i < softBreakCount) {
    ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
    currentDrawOffset = softBreaks[i];
    i++;
  }
  ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
  free(unicharBuffer);
  free(softBreaks);
  
  // restore the cgcontext gstate
  CGContextRestoreGState(cgContext);
}
Esempio n. 7
0
static bool osx_draw_text_to_cgcontext_at_location(const void *p_text, uindex_t p_length, MCGPoint p_location, const MCGFont &p_font, CGContextRef p_cgcontext, MCGIntRectangle &r_bounds)
{	
	OSStatus t_err;
	t_err = noErr;	
	
	ATSUFontID t_font_id;
	Fixed t_font_size;
	t_font_size = p_font . size << 16;	
	
	ATSUAttributeTag t_tags[] =
	{
		kATSUFontTag,
		kATSUSizeTag,
	};
	ByteCount t_sizes[] =
	{
		sizeof(ATSUFontID),
		sizeof(Fixed),
	};
	ATSUAttributeValuePtr t_attrs[] =
	{
		&t_font_id,
		&t_font_size,
	};	
	
	ATSLineLayoutOptions t_layout_options;
	ATSUAttributeTag t_layout_tags[] =
	{
		kATSULineLayoutOptionsTag,
		kATSUCGContextTag,
	};
	ByteCount t_layout_sizes[] =
	{
		sizeof(ATSLineLayoutOptions),
		sizeof(CGContextRef),
	};
	ATSUAttributeValuePtr t_layout_attrs[] =
	{
		&t_layout_options,
		&p_cgcontext,
	};	
	
	if (t_err == noErr)
	{
		// if the specified fon't can't be found, just use the default
		if (ATSUFONDtoFontID((short)(intptr_t)p_font . fid, p_font . style, &t_font_id) != noErr)
			t_err = ATSUFONDtoFontID(0, p_font . style, &t_font_id);
	}
	
	ATSUStyle t_style;
	t_style = NULL;
	if (t_err == noErr)
		t_err = ATSUCreateStyle(&t_style);
	if (t_err == noErr)
		t_err = ATSUSetAttributes(t_style, sizeof(t_tags) / sizeof(ATSUAttributeTag), t_tags, t_sizes, t_attrs);
	
	ATSUTextLayout t_layout;
	t_layout = NULL;
	if (t_err == noErr)
	{
		UniCharCount t_run;
		t_run = p_length / 2;
		t_err = ATSUCreateTextLayoutWithTextPtr((const UniChar *)p_text, 0, p_length / 2, p_length / 2, 1, &t_run, &t_style, &t_layout);
	}
	if (t_err == noErr)
		t_err = ATSUSetTransientFontMatching(t_layout, true);
	if (t_err == noErr)
	{
		t_layout_options = kATSLineUseDeviceMetrics | kATSLineFractDisable;
		t_err = ATSUSetLayoutControls(t_layout, sizeof(t_layout_tags) / sizeof(ATSUAttributeTag), t_layout_tags, t_layout_sizes, t_layout_attrs);
	}	
	
	MCGIntRectangle t_bounds;
	if (p_cgcontext == NULL)
	{
		ATSUTextMeasurement t_before, t_after, t_ascent, t_descent;
		if (t_err == noErr)
			t_err = ATSUGetUnjustifiedBounds(t_layout, 0, p_length / 2, &t_before, &t_after, &t_ascent, &t_descent);
		
		if (t_err == noErr)
		{
			t_ascent = (t_ascent + 0xffff) >> 16;
			t_descent = (t_descent + 0xffff) >> 16;
			t_after = (t_after + 0xffff) >> 16;
			
			t_bounds . x = p_location . x;
			t_bounds . y = p_location . y - p_font . ascent;
			t_bounds . width = t_after;
			t_bounds . height = p_font . descent + p_font . ascent;
			
			r_bounds = t_bounds;
		}
static
OSStatus AddNewTextLayoutToContext( 
	DrawContextStruct	*context )
{
	OSStatus				err = noErr;
	ATSUAttributeTag		tag;
	ByteCount				valueSize;
	ATSUAttributeValuePtr	valuePtr;
	UniCharCount			runLength = kATSUToTextEnd;
	
	if (context->cgContext == NULL)
		return err;

	// create a text layout object
	err = ATSUCreateTextLayoutWithTextPtr( context->textBuffer,
		kATSUFromTextBeginning, kATSUToTextEnd, context->characterCount, 1,
		&runLength, &gGlobalStyle, &context->layoutObject );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// add the cgContext to the text layout
	tag = kATSUCGContextTag;
	valueSize = sizeof( CGContextRef );
	valuePtr = &context->cgContext;
	err = ATSUSetLayoutControls( context->layoutObject, 1, &tag, &valueSize, &valuePtr );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// set font substitution for the new layout	
	err = ATSUSetTransientFontMatching( context->layoutObject, true );
	require_noerr( err, AddNewTextLayoutToContext_err );
	
	// now, check the menu and see if we need to install a callback
	switch ( gDemoMenuSelection )
	{
		case kDemoMenuItemStretch:
			err = InstallStrechyGlyphCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
			
		case kDemoMenuItemShrink:
			err = InstallShrinkyGlyphCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
		
		case kDemoMenuItemWhitespaceReplace:		
			err = InstallGlyphReplacementCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
			
		case kDemoMenuItemSineWave:
			err = InstallGlyphWaveCallback( context->layoutObject );
			require_noerr( err, AddNewTextLayoutToContext_err );
			break;
		
		case kDemoMenuItemNone:
		default:		
			break;
			
	}

AddNewTextLayoutToContext_err:
	
	return err;
}
static
OSStatus ResizeDemoWindow(
	EventRef 	inEvent, 
	WindowRef 	windowRef )
{
	OSStatus			err;
	Rect				newBounds;
	Rect				oldBounds;
	short				newWidth;
	short				newLength;
	HIViewRef			myHIViewRef;
	
	// get the event parameter which will tell us the new size
	err = GetEventParameter( inEvent, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof( Rect ), NULL, &newBounds );
	require_noerr( err, ResizeDemoWindow_err );

	// get the old bounds, just to see if we don't need to draw anything
	err = GetEventParameter( inEvent, kEventParamPreviousBounds,  typeQDRectangle, NULL, sizeof( Rect ), NULL, &oldBounds );
	require_noerr( err, ResizeDemoWindow_err );		
	
	// calculate the new width and length
	newWidth = newBounds.right - newBounds.left;
	newLength = newBounds.bottom - newBounds.top;
	
	// check to see if we need to redraw. If this is a simple translation,
	// then we don't.
	if ( ( newLength != ( oldBounds.bottom - oldBounds.top ) ) ||
		 ( newWidth !=	( oldBounds.right - oldBounds.left ) ) )
	{
		DrawContextStruct	*windowContext;
		CGrafPtr			windowPort;
	
		// get the draw context struct from the window's refCon
		windowContext = (DrawContextStruct *) GetWRefCon( windowRef );

#if BUGWORKAROUNDS
		
		// get the window port
		windowPort = GetWindowPort( windowRef );
		
		if (windowContext->cgContext == NULL)
			return err;
			
		// okay, so this is really, really lame. I'm going to get rid of
		// the current cg context and get a new one. This is because I
		// don't have the time right now to figure out how to synchronize the
		// clipping regions and such for the window and the context. This
		// is really bad, beacuse the text layout needs to have the new
		// cg context tag set in it, which will invalidate the layout.
		
		// I only need to dispose of the context each time until I figure
		// out what's going wrong with the Quickdraw clipping regions.
		
		// dispose of the context
		// make sure that the context is re-set in the ATSUI object
		if ( windowContext->layoutObject != NULL )
		{
			ATSUAttributeTag tag = kATSUCGContextTag;
			ByteCount valueSize = sizeof( CGContextRef );
			ATSUAttributeValuePtr valuePtr = &windowContext->cgContext;
			
			err = ATSUSetLayoutControls( windowContext->layoutObject, 1, &tag,
				&valueSize, &valuePtr );
			require_noerr( err, ResizeDemoWindow_err );
			
		}
#endif
		
		// redraw the context
		HIViewFindByID(HIViewGetRoot(windowRef), myHIViewID, &myHIViewRef);
		HIViewSetNeedsDisplay( myHIViewRef, true);
	}

ResizeDemoWindow_err:

	return eventNotHandledErr;	

}
Esempio n. 10
0
bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
                                               QTextEngine::ShaperFlags flags, QShaperItem *shaperItem) const
{
    //qDebug() << "stringToCMap" << QString(str, len);

    OSStatus e = noErr;

    e = ATSUSetTextPointerLocation(textLayout, (UniChar *)(str), 0, len, len);
    if (e != noErr) {
        qWarning("Qt: internal: %ld: Error ATSUSetTextPointerLocation %s: %d", long(e), __FILE__, __LINE__);
        return false;
    }

    QGlyphLayoutInfo nfo;
    nfo.glyphs = glyphs;
    nfo.numGlyphs = nglyphs;
    nfo.callbackCalled = false;
    nfo.flags = flags;
    nfo.shaperItem = shaperItem;

    QVarLengthArray<int> mappedFonts(len);
    for (int i = 0; i < len; ++i)
        mappedFonts[i] = 0;
    nfo.mappedFonts = mappedFonts.data();

    Q_ASSERT(sizeof(void *) <= sizeof(URefCon));
    e = ATSUSetTextLayoutRefCon(textLayout, (URefCon)&nfo);
    if (e != noErr) {
        qWarning("Qt: internal: %ld: Error ATSUSetTextLayoutRefCon %s: %d", long(e), __FILE__, __LINE__);
        return false;
    }

    {
        const int maxAttributeCount = 3;
        ATSUAttributeTag tags[maxAttributeCount + 1];
        ByteCount sizes[maxAttributeCount + 1];
        ATSUAttributeValuePtr values[maxAttributeCount + 1];
        int attributeCount = 0;

        tags[attributeCount] = kATSULineLayoutOptionsTag;
        ATSLineLayoutOptions layopts = kATSLineHasNoOpticalAlignment
                                       | kATSLineIgnoreFontLeading
                                       | kATSLineNoSpecialJustification // we do kashidas ourselves
                                       | kATSLineDisableAllJustification
                                       ;

        if (!(flags & QTextEngine::DesignMetrics)) {
            layopts |= kATSLineFractDisable | kATSLineUseDeviceMetrics
                       | kATSLineDisableAutoAdjustDisplayPos;
        }

        if (fontDef.styleStrategy & QFont::NoAntialias)
            layopts |= kATSLineNoAntiAliasing;

        if (!kerning)
            layopts |= kATSLineDisableAllKerningAdjustments;

        values[attributeCount] = &layopts;
        sizes[attributeCount] = sizeof(layopts);
        ++attributeCount;

        tags[attributeCount] = kATSULayoutOperationOverrideTag;
        ATSULayoutOperationOverrideSpecifier spec;
        spec.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
        spec.overrideUPP = atsuPostLayoutCallback;
        values[attributeCount] = &spec;
        sizes[attributeCount] = sizeof(spec);
        ++attributeCount;

        Boolean direction;
        if (flags & QTextEngine::RightToLeft)
            direction = kATSURightToLeftBaseDirection;
        else
            direction = kATSULeftToRightBaseDirection;
        tags[attributeCount] = kATSULineDirectionTag;
        values[attributeCount] = &direction;
        sizes[attributeCount] = sizeof(direction);
        ++attributeCount;

        Q_ASSERT(attributeCount < maxAttributeCount + 1);
        e = ATSUSetLayoutControls(textLayout, attributeCount, tags, sizes, values);
        if (e != noErr) {
            qWarning("Qt: internal: %ld: Error ATSUSetLayoutControls %s: %d", long(e), __FILE__, __LINE__);
            return false;
        }

    }

    e = ATSUSetRunStyle(textLayout, style, 0, len);
    if (e != noErr) {
        qWarning("Qt: internal: %ld: Error ATSUSetRunStyle %s: %d", long(e), __FILE__, __LINE__);
        return false;
    }

    if (!(fontDef.styleStrategy & QFont::NoFontMerging)) {
        int pos = 0;
        do {
            ATSUFontID substFont = 0;
            UniCharArrayOffset changedOffset = 0;
            UniCharCount changeCount = 0;

            e = ATSUMatchFontsToText(textLayout, pos, len - pos,
                                     &substFont, &changedOffset,
                                     &changeCount);
            if (e == kATSUFontsMatched) {
                int fontIdx = fontIndexForFontID(substFont);
                for (uint i = 0; i < changeCount; ++i)
                    mappedFonts[changedOffset + i] = fontIdx;
                pos = changedOffset + changeCount;
                ATSUSetRunStyle(textLayout, engineAt(fontIdx)->style, changedOffset, changeCount);
            } else if (e == kATSUFontsNotMatched) {
                pos = changedOffset + changeCount;
            }
        } while (pos < len && e != noErr);
    }
    {    // trigger the a layout
        Rect rect;
        e = ATSUMeasureTextImage(textLayout, kATSUFromTextBeginning, kATSUToTextEnd,
                                 /*iLocationX =*/ 0, /*iLocationY =*/ 0,
                                 &rect);
        if (e != noErr) {
            qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage %s: %d", long(e), __FILE__, __LINE__);
            return false;
        }
    }

    if (!nfo.callbackCalled) {
            qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage did not trigger callback %s: %d", long(e), __FILE__, __LINE__);
            return false;
    }

    ATSUClearLayoutCache(textLayout, kATSUFromTextBeginning);
    return true;
}
Esempio n. 11
0
void
DoAtsuiLayout(void* p, int justify)
{
	memoryword*	node = (memoryword*)p;

	unsigned	f = native_font(node);
	if (fontarea[f] != AAT_FONT_FLAG) {
		fprintf(stderr, "internal error: do_atsui_layout called for non-ATSUI font\n");
		exit(1);
	}

	if (sTextLayout == 0)
		InitializeLayout();

	OSStatus	status = noErr;
	
	long		txtLen = native_length(node);
	const UniChar*	txtPtr = (UniChar*)(node + native_node_size);

	status = ATSUSetTextPointerLocation(sTextLayout, txtPtr, 0, txtLen, txtLen);
	
	// we're using this font in AAT mode, so fontlayoutengine[f] is actually an ATSUStyle
	ATSUStyle	style = (ATSUStyle)(fontlayoutengine[native_font(node)]);
	status = ATSUSetRunStyle(sTextLayout, style, 0, txtLen);

	ATSUAttributeTag		tags[] = { kATSULineWidthTag, kATSULineJustificationFactorTag };
	ItemCount				numTags = sizeof(tags) / sizeof(ATSUAttributeTag);
	if (justify) {
		ByteCount				valSizes[] = { sizeof(Fixed), sizeof(Fract) };
		Fixed					wid = FixedTeXtoPSPoints(node_width(node));
		Fract					just = fract1;
		ATSUAttributeValuePtr	valPtrs[] = { &wid, &just };
		status = ATSUSetLayoutControls(sTextLayout, numTags, tags, valSizes, valPtrs);
	}
	
	ItemCount	count;
	ATSLayoutRecord*	layoutRec = NULL;
	status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(sTextLayout, 0,
		kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec, &count);

	int i;
	int	realGlyphCount = 0;
	int lastRealGlyph = 0;
	for (i = 0; i < count; ++i)
		if (layoutRec[i].glyphID < 0xfffe) {
			lastRealGlyph = i;
			++realGlyphCount;
		}

	void*		glyph_info = xmalloc(realGlyphCount * native_glyph_info_size);
	FixedPoint*	locations = (FixedPoint*)glyph_info;
	UInt16*		glyphIDs = (UInt16*)(locations + realGlyphCount);

	Fixed		lsUnit = justify ? 0 : fontletterspace[f];
	Fixed		lsDelta = 0;

	realGlyphCount = 0;
	for (i = 0; i < count; ++i) {
		if (layoutRec[i].glyphID < 0xfffe) {
			if ((layoutRec[i].flags & kATSGlyphInfoIsAttachment) && (lsDelta != 0))
				lsDelta -= lsUnit;
			glyphIDs[realGlyphCount] = layoutRec[i].glyphID;
			locations[realGlyphCount].y = 0;	/* FIXME: won't handle baseline offsets */
			locations[realGlyphCount].x = FixedPStoTeXPoints(layoutRec[i].realPos) + lsDelta;
			lsDelta += lsUnit;
			++realGlyphCount;
		}
	}
	if (lsDelta != 0)
		lsDelta -= lsUnit;

	native_glyph_count(node) = realGlyphCount;
	native_glyph_info_ptr(node) = glyph_info;
	
	if (!justify)
		node_width(node) = FixedPStoTeXPoints(layoutRec[count-1].realPos) + lsDelta;

	ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void*)&layoutRec);

	if (justify)
		ATSUClearLayoutControls(sTextLayout, numTags, tags);
}
Esempio n. 12
0
OSStatus ATSTextLayoutSetContext(ATSUTextLayout lay, CGContextRef con) {
  ATSUAttributeTag tag[1] = {kATSUCGContextTag};
  ByteCount       count[1] = {sizeof(con)};
  ATSUAttributeValuePtr val[1] = {con};
  return ATSUSetLayoutControls( lay, 1, tag, count, val);
}
Esempio n. 13
0
static
OSStatus DrawLayoutForStyleAndRunInfo( 
	ATSUStyle			styleArray[], 
	ItemCount			styleArraySize,
	ATSUStyleRunInfo	styleRunArray[],
	ItemCount			styleRunArraySize,
	UniChar				*stringPtr,
	UniCharCount		stringLen,
	CGContextRef		cgContext,
	Fixed				currentXPos,
	Fixed				*currentYPos  )
{
	OSStatus				err;
	ATSUStyle				*seperateStyles = NULL;
	UniCharCount			*seperateRunLengths = NULL;
	ItemCount				numberOfRuns = 0;
	ATSUAttributeTag		attrTag;
	ByteCount				attrSize;
	ATSUAttributeValuePtr	attrPtr;
	ATSUTextLayout			newLayout;
	
	// check to see if we have a style array
	if ( styleArray != NULL )
	{
		// if the styleRunArray is NULL, then there is only one run
		if ( styleRunArray == NULL )
		{
			numberOfRuns = 1;
			seperateStyles = styleArray;
			seperateRunLengths = &stringLen;
		}
		else
		{
			ItemCount	i;
		
			// the number of runs is equal to the number of runs passed in
			numberOfRuns = styleRunArraySize;
		
			// allocate a seperateStyles and seperateRuns array
			seperateStyles = (ATSUStyle *) malloc( sizeof( ATSUStyle ) * 
				numberOfRuns );
			require_action( seperateStyles != NULL, 
				CreateLayoutForStyleAndRunInfo_err, err = memFullErr );
				
			seperateRunLengths = (UniCharCount *) malloc( sizeof( UniCharCount ) *
				numberOfRuns );
			require_action( seperateRunLengths != NULL, 
				CreateLayoutForStyleAndRunInfo_err, err = memFullErr );
				
			// loop through and assign the runs to the seperate arrays. I'm not
			// sure that this is the best way to do this. Perhaps it's best to
			// simply create the layout and assign the style runs to it individually.
			for ( i = 0; i < numberOfRuns; i++ )
			{
				seperateStyles[i] = styleArray[styleRunArray[i].styleObjectIndex];
				seperateRunLengths[i] = styleRunArray[i].runLength;
			}
			
		}
		
	}

	// first of all, create the layout with the text information passed in
	err = ATSUCreateTextLayoutWithTextPtr( stringPtr, kATSUFromTextBeginning,
		kATSUToTextEnd, stringLen, numberOfRuns, seperateRunLengths, seperateStyles,
		&newLayout );
	require_noerr( err, CreateLayoutForStyleAndRunInfo_err );
	
	// if we've got a layout, then assign the CGContext to it
	attrTag = kATSUCGContextTag;
	attrSize = sizeof( CGContextRef );
	attrPtr = &cgContext;
	
	err = ATSUSetLayoutControls( newLayout, 1, &attrTag, &attrSize, &attrPtr );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
	// set the Y position before we draw
	err = SetYPositionForLineHeight( newLayout, currentYPos );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
	// do some drawin'
	err = ATSUDrawText( newLayout, kATSUFromTextBeginning, kATSUToTextEnd,
		currentXPos, *currentYPos );
	require_noerr( err, CreateLayoutForStyleAndRunInfoLayout_err );
	
CreateLayoutForStyleAndRunInfoLayout_err:

	ATSUDisposeTextLayout( newLayout );
	
CreateLayoutForStyleAndRunInfo_err:

	if ( ( styleRunArray != NULL ) && ( styleArray != NULL ) ) 
	{
		if ( seperateStyles != NULL )
		{
			free( seperateStyles );
		}
		
		if ( seperateRunLengths != NULL );
		{
			free( seperateRunLengths );
		}
		
	}
	
	return err;

}