Esempio n. 1
0
int
getotmathitalcorr(int f, int g)
{
	int	rval = 0;
	
	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);

		const char* table = (const char*)font->getFontTable(kMATHTableTag);
		if (table == NULL)
			return rval;

		le_uint16	offset = SWAPW(((const MathTableHeader*)table)->mathGlyphInfo);
		if (offset == 0)
			return rval;
		const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset);

		offset = SWAPW(glyphInfo->mathItalicsCorrectionInfo);
		if (offset == 0)
			return rval;
		const MathItalicsCorrectionInfo* italCorrInfo = (const MathItalicsCorrectionInfo*)(((const char*)glyphInfo) + offset);

		offset = SWAPW(italCorrInfo->coverage);
		if (offset == 0)
			return rval;
		const CoverageTable* coverage = (const CoverageTable*)(((const char*)italCorrInfo) + offset);

		le_int32	index = coverage->getGlyphCoverage(g);
		if (index >= 0 && index < SWAPW(italCorrInfo->italicsCorrectionCount))
			rval = X2Fix(SWAPW(italCorrInfo->italicsCorrection[index].value) * Fix2X(fontsize[f]) / font->getUnitsPerEM());
	}
	
	return rval;
}
Esempio n. 2
0
oop ATSUGetUnjustifiedBounds_wrap( ATSUTextLayout     iTextLayout, 
                                   int                iLineStart,  // uint32
                                   int                iLineLength, // uint32
                                   void*              FH ) {
  ATSUTextMeasurement oTextBefore, oTextAfter, oAscent, oDescent;
  OSStatus e = ATSUGetUnjustifiedBounds( 
   iTextLayout, (uint32)iLineStart, (uint32)iLineLength, 
   &oTextBefore, &oTextAfter, &oAscent, &oDescent );
  if (e != noErr) {
      return  (oop)reportOSError(e, "ATSUGetUnjustifiedBounds", FH);
  }
  objVectorOop r = Memory->objVectorObj->cloneSize(4);
  r->obj_at_put(0, as_floatOop(Fix2X(oTextBefore)), false);
  r->obj_at_put(1, as_floatOop(Fix2X(oAscent)),     false);
  r->obj_at_put(2, as_floatOop(Fix2X(oTextAfter)),  false);
  r->obj_at_put(3, as_floatOop(Fix2X(oDescent)),    false);
  return r;
}
Esempio n. 3
0
int
otpartfulladvance(int f, const GlyphAssembly* a, int i)
{
	int	rval = 0;
	
	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);
		rval = X2Fix(SWAPW(a->partRecords[i].fullAdvance) * Fix2X(fontsize[f]) / font->getUnitsPerEM());
	}
	
	return rval;
}
Esempio n. 4
0
int
getotmathconstant(int f, int n)
{
	int	rval = 0;

	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);
		rval = getMathConstant(font, (mathConstantIndex)n);
		/* scale according to font size, except the ones that are percentages */
		if (n > scriptScriptPercentScaleDown && n < radicalDegreeBottomRaisePercent)
			rval = X2Fix(rval * Fix2X(fontsize[f]) / font->getUnitsPerEM());
	}
	return rval;
}
Esempio n. 5
0
// Checks the global preference to see if text at the specified point size
// will be drawn antialiased or not.
//
// Note that iSize is of type Fixed!
//
Boolean IsAntiAliased(Fixed iSize)
{
    Boolean keyExistsAndHasValidFormat;
    CFIndex value;

    value = CFPreferencesGetAppIntegerValue( CFSTR("AppleAntiAliasingThreshold"),
                                             kCFPreferencesCurrentApplication,
                                             &keyExistsAndHasValidFormat );

    if ( keyExistsAndHasValidFormat )
        return ( Fix2X(iSize) > value ); // 'value' is the maximum not-antialiasing size
    else
        return true;
}
Esempio n. 6
0
/*------------------------------------ cmd_Volumeq ---*/
Pvoid
cmd_Volumeq(SpeakPtr xx)
{
  EnterCallback();
  if (xx && xx->fSpeaker)
  {
    Atom  response[1];
    Fixed volume;

    GetSpeechInfo(xx->fSpeaker, soVolume, &volume);
    SETFLOAT(response, float(Fix2X(volume)));
    outlet_anything(xx->fResultOut, gVolumeSymbol, 1, response);
  }
  ExitMaxMessageHandler()
} /* cmd_Volumeq */
Esempio n. 7
0
void
XeTeXFontMgr::getOpSizeRecAndStyleFlags(Font* theFont)
{
	XeTeXFont	font = createFont(theFont->fontRef, 655360);
	if (font != 0) {
		const OpSizeRec* pSizeRec = getOpSizePtr(font);
		if (pSizeRec != NULL) {
			theFont->opSizeInfo.designSize = SWAP(pSizeRec->designSize);
			if (SWAP(pSizeRec->subFamilyID) == 0
				&& SWAP(pSizeRec->nameCode) == 0
				&& SWAP(pSizeRec->minSize) == 0
				&& SWAP(pSizeRec->maxSize) == 0)
				goto done_size;	// feature is valid, but no 'size' range
			theFont->opSizeInfo.subFamilyID = SWAP(pSizeRec->subFamilyID);
			theFont->opSizeInfo.nameCode = SWAP(pSizeRec->nameCode);
			theFont->opSizeInfo.minSize = SWAP(pSizeRec->minSize);
			theFont->opSizeInfo.maxSize = SWAP(pSizeRec->maxSize);
		}
	done_size:

		const OS2TableHeader* os2Table = (const OS2TableHeader*)getFontTablePtr(font, LE_OS_2_TABLE_TAG);
		if (os2Table != NULL) {
			theFont->weight = SWAP(os2Table->usWeightClass);
			theFont->width = SWAP(os2Table->usWidthClass);
			UInt16 sel = SWAP(os2Table->fsSelection);
			theFont->isReg = (sel & (1 << 6)) != 0;
			theFont->isBold = (sel & (1 << 5)) != 0;
			theFont->isItalic = (sel & (1 << 0)) != 0;
		}

		const HEADTable* headTable = (const HEADTable*)getFontTablePtr(font, LE_HEAD_TABLE_TAG);
		if (headTable != NULL) {
			UInt16	ms = SWAP(headTable->macStyle);
			if ((ms & (1 << 0)) != 0)
				theFont->isBold = true;
			if ((ms & (1 << 1)) != 0)
				theFont->isItalic = true;
		}

		const POSTTable* postTable = (const POSTTable*)getFontTablePtr(font, LE_POST_TABLE_TAG);
		if (postTable != NULL) {
			theFont->slant = (int)(1000 * (tan(Fix2X(-SWAP(postTable->italicAngle)) * M_PI / 180.0)));
		}
		deleteFont(font);
	}
}
Esempio n. 8
0
oop ATSUGetGlyphBounds_wrap( ATSUTextLayout     iTextLayout, 
                             float              fTextBasePointX,
                             float              fTextBasePointY,
                             int                iBoundsCharStart,  // uint32
                             int                iBoundsCharLength, // uint32
                             uint16             iTypeOfBounds,
                             void*              FH ) {
  ATSUTextMeasurement iTextBasePointX = X2Fix(fTextBasePointX);
  ATSUTextMeasurement iTextBasePointY = X2Fix(fTextBasePointY);
  
  ATSTrapezoid b;
  ItemCount oActualNumberOfBounds;
  
  OSStatus e = ATSUGetGlyphBounds( 
    iTextLayout,
    iTextBasePointX,  iTextBasePointY,
    iBoundsCharStart, iBoundsCharLength,
    iTypeOfBounds,
    1, //   ItemCount iMaxNumberOfBounds,
    &b, &oActualNumberOfBounds);       /* can be NULL */ 

  if (e != noErr) {
      return  (oop)reportOSError(e, "ATSUGetGlyphBounds", FH);
  }
  if (oActualNumberOfBounds < 1) {
   static char buf[1000];
    sprintf(buf, "ATSUGetGlyphBounds failed: returned %d bounds instead of 1", (int)oActualNumberOfBounds);
    failure(FH, buf);
    return NULL;
  }
  float L = min((float)Fix2X(b.upperLeft.x), (float)Fix2X(b.lowerLeft.x ));
  float T = max((float)Fix2X(b.upperLeft.y), (float)Fix2X(b.upperRight.y));
  
  float R = min((float)Fix2X(b.upperRight.x), (float)Fix2X(b.lowerRight.x));
  float B = max((float)Fix2X(b.lowerLeft.y ), (float)Fix2X(b.lowerRight.y));

  objVectorOop r = Memory->objVectorObj->cloneSize(4);
  r->obj_at_put(0, as_floatOop(L), false);
  r->obj_at_put(1, as_floatOop(T), false);
  r->obj_at_put(2, as_floatOop(R), false);
  r->obj_at_put(3, as_floatOop(B), false);
  return r;
}
Esempio n. 9
0
P1(PUBLIC pascal trap, Fract, FracSin, Fixed, x)	/* IMIV-64 */
{
    Extended z;
    LONGINT oct;

    if (x < 0)
	x += (-(x+1) / (POVER4 * 8) + 1) * POVER4 * 8;
    oct = x / POVER4 % 8;
    x %= POVER4 * 4;
    switch (oct) {
    case 0:
	z = sin(Fix2X(x));
	break;
    case 1:
	z = cos(Fix2X(POVER4 * 2 - x));
	break;
    case 2:
	z = cos(Fix2X(x - POVER4 * 2));
	break;
    case 3:
	z = sin(Fix2X(POVER4 * 4 - x));
	break;
    case 4:
	z = -sin(Fix2X(x));
	break;
    case 5:
	z = -cos(Fix2X(POVER4 * 2 - x));
	break;
    case 6:
	z = -cos(Fix2X(x - POVER4 * 2));
	break;
    case 7:
	z = -sin(Fix2X(POVER4 * 4 - x));
	break;
    }
    return X2Frac(&z);
}
Esempio n. 10
0
int
getotmathvariant(int f, int g, int v, integer* adv, int horiz)
{
	int	rval = g;
	*adv = -1;
	
	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);

		const char* table = (const char*)font->getFontTable(kMATHTableTag);
		if (table == NULL)
			return rval;

		le_uint16	offset = SWAPW(((const MathTableHeader*)table)->mathVariants);
		if (offset == 0)
			return rval;
		const MathVariants* variants = (const MathVariants*)(table + offset);

		offset = horiz ? SWAPW(variants->horizGlyphCoverage) : SWAPW(variants->vertGlyphCoverage);
		if (offset == 0)
			return rval;
		const CoverageTable* coverage = (const CoverageTable*)(((const char*)variants) + offset);

		le_int32	index = coverage->getGlyphCoverage(g);
		if (index >= 0) {
			if (horiz)
				index += SWAPW(variants->vertGlyphCount);
			const MathGlyphConstruction*	construction = (const MathGlyphConstruction*)(((const char*)variants)
															+ SWAPW(variants->vertGlyphConstruction[index]));
			if (v < SWAPW(construction->variantCount)) {
				rval = SWAPW(construction->mathGlyphVariantRecord[v].variantGlyph);
				*adv = X2Fix(SWAPW(construction->mathGlyphVariantRecord[v].advanceMeasurement)
								* Fix2X(fontsize[f]) / font->getUnitsPerEM());
			}
		}
	}
	
	return rval;
}
Esempio n. 11
0
int
otminconnectoroverlap(int f)
{
	int	rval = 0;
	
	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);

		const char* table = (const char*)font->getFontTable(kMATHTableTag);
		if (table == NULL)
			return rval;

		le_uint16	offset = SWAPW(((const MathTableHeader*)table)->mathVariants);
		if (offset == 0)
			return rval;
		const MathVariants* variants = (const MathVariants*)(table + offset);

		rval = X2Fix(SWAPW(variants->minConnectorOverlap) * Fix2X(fontsize[f]) / font->getUnitsPerEM());
	}

	return rval;
}
/*

Calculate the static frame rate for a given movie.

*/
void MovieGetStaticFrameRate(Movie inMovie, double *outStaticFrameRate)
{

  *outStaticFrameRate = 0;

  Media movieMedia;
  MediaHandler movieMediaHandler;
  /* get the media identifier for the media that contains the first
    video track's sample data, and also get the media handler for
    this media. */
  MovieGetVideoMediaAndMediaHandler(inMovie, &movieMedia, &movieMediaHandler);
  if (movieMedia && movieMediaHandler)
  {
    Boolean isMPEG = false;
    /* is this the MPEG-1/MPEG-2 media handler? */
    OSErr err = IsMPEGMediaHandler(movieMediaHandler, &isMPEG);
    if (err == noErr)
    {
      if (isMPEG) /* working with MPEG-1/MPEG-2 media */
      {
        Fixed staticFrameRate;
        ComponentResult err = MPEGMediaGetStaticFrameRate(movieMediaHandler, &staticFrameRate);
        if (err == noErr)
        {
          /* convert Fixed data result to type double */
          *outStaticFrameRate = Fix2X(staticFrameRate);
        }
      }
      else  /* working with non-MPEG-1/MPEG-2 media */
      {
        OSErr err = MediaGetStaticFrameRate(movieMedia, outStaticFrameRate);
        if (err != noErr) ofLog(OF_LOG_ERROR, "error in MediaGetStaticFrameRate, ofQtUtils");
        //assert(err == noErr);
      }
    }
  }
}
Esempio n. 13
0
int
getotmathaccentpos(int f, int g)
{
	int	rval = 0x7fffffffUL;
	
	if (fontarea[f] == OTGR_FONT_FLAG) {
		XeTeXFontInst*	font = (XeTeXFontInst*)getFont((XeTeXLayoutEngine)fontlayoutengine[f]);

		const char* table = (const char*)font->getFontTable(kMATHTableTag);
		if (table == NULL)
			return rval;

		le_uint16	offset = SWAPW(((const MathTableHeader*)table)->mathGlyphInfo);
		if (offset == 0)
			return rval;
		const MathGlyphInfo* glyphInfo = (const MathGlyphInfo*)(table + offset);

		offset = SWAPW(glyphInfo->mathTopAccentAttachment);
		if (offset == 0)
			return rval;
		const MathTopAccentAttachment* accentAttachment = (const MathTopAccentAttachment*)(((const char*)glyphInfo) + offset);

		offset = SWAPW(accentAttachment->coverage);
		if (offset == 0)
			return rval;
		const CoverageTable* coverage = (const CoverageTable*)(((const char*)accentAttachment) + offset);

		le_int32	index = coverage->getGlyphCoverage(g);
		if (index >= 0 && index < SWAPW(accentAttachment->topAccentAttachmentCount)) {
			rval = (le_int16)SWAPW(accentAttachment->topAccentAttachment[index].value);
			rval = X2Fix(rval * Fix2X(fontsize[f]) / font->getUnitsPerEM());
		}
	}
	
	return rval;
}
Esempio n. 14
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. 15
0
static inline Fixed
FixedTeXtoPSPoints(Fixed pts)
{
	return X2Fix(TeXtoPSPoints(Fix2X(pts)));
}
Esempio n. 16
0
// Draws the current ATSUI data.  Takes a GrafPtr as an argument so
// that it can handle printing as well as drawing into a window.
//
void DrawATSUIStuff(GrafPtr drawingPort)
{
    GrafPtr                             savedPort;
    Rect                                portBounds, quarterRect2, quarterRect3;
    float								windowHeight, quarter;
    CGContextRef						context;
    TXNTextBoxOptionsData				optionsData;
    Boolean								needToUseCGStrokeMethod;

    // Set up the GrafPort
    GetPort(&savedPort);
    SetPort(drawingPort);
    GetPortBounds(drawingPort, &portBounds);
    EraseRect(&portBounds);

    // Divide the window into vertical quarters, and draw the text in the middle two quarters
    windowHeight = portBounds.bottom - portBounds.top;
    quarter = windowHeight / 4.0;
    MacSetRect(&quarterRect2, portBounds.left, portBounds.top + quarter, portBounds.right, portBounds.bottom - (quarter * 2.0));
    FrameRect(&quarterRect2);
    MacSetRect(&quarterRect3, portBounds.left, portBounds.top + (quarter * 2.0), portBounds.right, portBounds.bottom - quarter);
    FrameRect(&quarterRect3);

    // Set up the CGContext
    if (gNewCG) QDBeginCGContext(drawingPort, &context); else CreateCGContextForPort(drawingPort, &context);

    // Setup the options to pass into TXNDrawUnicodeTextBox
    optionsData.optionTags = kTXNUseCGContextRefMask | kTXNSetFlushnessMask | kTXNUseFontFallBackMask;
    optionsData.flushness = X2Frac(0.5);   // Center the text horizontally, just for this demo.
    optionsData.options = (void *)context; // This parameter really needs to be renamed, see 3198383.

    // Draw the text once without the extr bold
    verify_noerr( TXNDrawUnicodeTextBox(gText, gLength, &quarterRect2, gStyle, &optionsData) );

    // ----------------------------------------------------------
    //
    // Here is where we change the setting to do the extra stroke
    // The value of gStrokeThicknessFactor determines how thick the extra stroke is.
    //   The "standard" value used by ATSUI is 0.024;
    //     this was changed to 0.044 for bug 3189696,
    //     and will probably be changed back, so if you
    //     want the extra stroke, you will have to do it
    //     manually, as is done below.
    //
    // The extra stroke method:
    //  - will look good on-screen when CG anti-aliasing is ON
    //  - will look good when printing
    //  - will *NOT* look good on-screen when CG anti-aliasing is OFF
    //     (just use kATSUQDBoldfaceTag in that case)
    //
    needToUseCGStrokeMethod = gCurrentlyPrinting || IsAntiAliased(gPointSize);
    if ( needToUseCGStrokeMethod ) {
        CGContextSaveGState(context);
        CGContextSetTextDrawingMode(context, kCGTextFillStroke);
        CGContextSetLineWidth(context, gStrokeThicknessFactor * Fix2X(gPointSize));
        // You might want to call CGContextSetStrokeColor() here,
        // just to make certain it is the same as the text/fill color.
    }
    else
        MySetBoldfaceTag(gStyle); // This will look very strong on-screen when CG anti-aliasing is off

    // Draw the text again with the extra bold for comparison
    verify_noerr( TXNDrawUnicodeTextBox(gText, gLength, &quarterRect3, gStyle, &optionsData) );

    // Undo the previous CG text mode setting
    if ( needToUseCGStrokeMethod )
        CGContextRestoreGState(context);
    else
        MyClearBoldfaceTag(gStyle);

    // Tear down the CGContext since we are done with it
    if (gNewCG) QDEndCGContext(drawingPort, &context); else CGContextRelease(context);    

    // Restore the GrafPort
    SetPort(savedPort);
}
Esempio n. 17
0
static inline Fixed
FixedPStoTeXPoints(Fixed pts)
{
	return X2Fix(PStoTeXPoints(Fix2X(pts)));
}
PsychError SCREENTextBounds(void) 
{
	//for debugging
	TextEncodingBase		textEncodingBase;
	TextEncodingVariant		textEncodingVariant;
	TextEncodingFormat		textEncodingFormat;
	
	///////
        PsychWindowRecordType           *winRec;
	char				*textCString;
	Str255				textPString;
	UniChar				*textUniString;
	OSStatus			callError;
	PsychRectType			resultPsychRect, resultPsychNormRect;
	ATSUTextLayout			textLayout;				//layout is a pointer to an opaque struct.
	int				stringLengthChars;
	int				uniCharBufferLengthElements, uniCharBufferLengthChars, uniCharBufferLengthBytes, yPositionIsBaseline;
	double			textHeightToBaseline;
	ByteCount			uniCharStringLengthBytes;
	TextToUnicodeInfo		textToUnicodeInfo;
	TextEncoding			textEncoding;
	ATSUStyle			atsuStyle;
	Boolean				foundFont;
	
	//for ATSU  style attributes
	PsychFontStructPtrType  psychFontRecord;

    			
        //all subfunctions should have these two lines.  
        PsychPushHelp(useString, synopsisString, seeAlsoString);
        if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
    
        //check for correct the number of arguments before getting involved
        PsychErrorExit(PsychCapNumInputArgs(5));   	
        PsychErrorExit(PsychRequireNumInputArgs(2)); 	
        PsychErrorExit(PsychCapNumOutputArgs(2));
	
	//get the window pointer and the text string and check that the window record has a font set
        PsychAllocInWindowRecordArg(1, kPsychArgRequired, &winRec);
	foundFont=PsychGetFontRecordFromFontNumber(winRec->textAttributes.textFontNumber, &psychFontRecord);
	if(!foundFont)
		PsychErrorExitMsg(PsychError_user, "Attempt to determine the bounds of text with no font or invalid font number");
		//it would be better to both prevent the user from setting invalid font numbers and init to the OS 9  default font.
	
	//read in the string and get its length and convert it to a unicode string.
	PsychAllocInCharArg(2, kPsychArgRequired, &textCString);
	stringLengthChars=strlen(textCString);
	if(stringLengthChars < 1) PsychErrorExitMsg(PsychError_user, "You asked me to compute the bounding box of an empty text string?!? Sorry, that's a no no...");
	if(stringLengthChars > 255) PsychErrorExitMsg(PsychError_unimplemented, "Cut corners and TextBounds will not accept a string longer than 255 characters");
	CopyCStringToPascal(textCString, textPString);
	uniCharBufferLengthChars= stringLengthChars * CHAR_TO_UNICODE_LENGTH_FACTOR;
	uniCharBufferLengthElements= uniCharBufferLengthChars + 1;		
	uniCharBufferLengthBytes= sizeof(UniChar) * uniCharBufferLengthElements;
	textUniString=(UniChar*)malloc(uniCharBufferLengthBytes);

    PsychCopyInDoubleArg(3, kPsychArgOptional, &(winRec->textAttributes.textPositionX));
    PsychCopyInDoubleArg(4, kPsychArgOptional, &(winRec->textAttributes.textPositionY));

	//Using a TextEncoding type describe the encoding of the text to be converteed.  
	textEncoding=CreateTextEncoding(kTextEncodingMacRoman, kMacRomanDefaultVariant, kTextEncodingDefaultFormat);
	//Take apart the encoding we just made to check it:
        textEncodingBase=GetTextEncodingBase(textEncoding);
        textEncodingVariant=GetTextEncodingVariant(textEncoding);
        textEncodingFormat=GetTextEncodingFormat(textEncoding);
	//Create a structure holding conversion information from the text encoding type we just created.
	callError=CreateTextToUnicodeInfoByEncoding(textEncoding,&textToUnicodeInfo);
	//Convert the text to a unicode string
	callError=ConvertFromPStringToUnicode(textToUnicodeInfo, textPString, (ByteCount)uniCharBufferLengthBytes,	&uniCharStringLengthBytes,	textUniString);
	//create the text layout object
	callError=ATSUCreateTextLayout(&textLayout);			
	//associate our unicode text string with the text layout object
	callError=ATSUSetTextPointerLocation(textLayout, textUniString, kATSUFromTextBeginning, kATSUToTextEnd, (UniCharCount)stringLengthChars);
	
	//create an ATSU style object
	callError=ATSUCreateStyle(&atsuStyle);
	callError=ATSUClearStyle(atsuStyle);
	
	//Not that we have a style object we have to set style charactersitics.  These include but are more general than Font Manager styles.  
	//ATSU Style objects have three sets of characteristics:  attributes, variations, and features.
	//attributes are things we need to set to match OS 9 behavior, such as the font ID, size, boldness, and italicization.
	//features are esoteric settings which we don't need for reproducing OS 9 behavior.  Whatever clearstyle sets should be fine.
	//font variations are axes of variation through the space of font characteristics.  The font definition includes available axes of variation.  Something else we can ignore for now.  
	PsychSetATSUStyleAttributesFromPsychWindowRecord(atsuStyle, winRec);
	//don't bother to set the variations of the style.
	//don't bother to set the features of the style.
	
	//associate the style with our layout object. This call assigns a style to every character of the string to be displayed.  
	callError=ATSUSetRunStyle(textLayout, atsuStyle, (UniCharArrayOffset)0, (UniCharCount)stringLengthChars);

	// Define the meaning of the y position of the specified drawing cursor.
	// We get the global setting from the Screen preference, but allow to override
	// it on a per-invocation basis via the optional 7th argument to 'DrawText':
	yPositionIsBaseline = PsychPrefStateGet_TextYPositionIsBaseline();
	PsychCopyInIntegerArg(5, kPsychArgOptional, &yPositionIsBaseline);
	 
	if (yPositionIsBaseline) {
		// Y position of drawing cursor defines distance between top of text and
		// baseline of text, i.e. the textheight excluding descenders of letters:

		// Need to compute offset via ATSU:
		ATSUTextMeasurement mleft, mright, mtop, mbottom;
        callError=ATSUGetUnjustifiedBounds(textLayout, kATSUFromTextBeginning, kATSUToTextEnd, &mleft, &mright, &mbottom, &mtop);
		if (callError) {
			PsychErrorExitMsg(PsychError_internal, "Failed to compute unjustified text height to baseline in call to ATSUGetUnjustifiedBounds().\n");    
		}

		// Only take height including ascenders into account, not the descenders.
		// MK: Honestly, i have no clue why this is the correct calculation (or if it is
		// the correct calculation), but visually it seems to provide the correct results
		// and i'm not a typographic expert and don't intend to become one...
		textHeightToBaseline = fabs(Fix2X(mbottom));
	}
	else {
		// Y position of drawing cursor defines top of text, therefore no offset (==0) needed:
		textHeightToBaseline = 0;
	}

	//Get the bounds for our text so that and create a texture of sufficient size to containt it. 
	ATSTrapezoid trapezoid;
	ItemCount oActualNumberOfBounds = 0;
	callError=ATSUGetGlyphBounds(textLayout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 0, NULL, &oActualNumberOfBounds);
	if (callError || oActualNumberOfBounds!=1) {
		PsychErrorExitMsg(PsychError_internal, "Failed to compute bounding box in call 1 to ATSUGetGlyphBounds() (nrbounds!=1)\n");    
	}
	callError=ATSUGetGlyphBounds(textLayout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &trapezoid, &oActualNumberOfBounds);
	if (callError || oActualNumberOfBounds!=1) {
		PsychErrorExitMsg(PsychError_internal, "Failed to retrieve bounding box in call 2 to ATSUGetGlyphBounds() (nrbounds!=1)\n");    
	}
	
	resultPsychRect[kPsychLeft]=(Fix2X(trapezoid.upperLeft.x) < Fix2X(trapezoid.lowerLeft.x)) ? Fix2X(trapezoid.upperLeft.x) : Fix2X(trapezoid.lowerLeft.x);
	resultPsychRect[kPsychRight]=(Fix2X(trapezoid.upperRight.x) > Fix2X(trapezoid.lowerRight.x)) ? Fix2X(trapezoid.upperRight.x) : Fix2X(trapezoid.lowerRight.x);
	resultPsychRect[kPsychTop]=(Fix2X(trapezoid.upperLeft.y) < Fix2X(trapezoid.upperRight.y)) ? Fix2X(trapezoid.upperLeft.y) : Fix2X(trapezoid.upperRight.y);
	resultPsychRect[kPsychBottom]=(Fix2X(trapezoid.lowerLeft.y) > Fix2X(trapezoid.lowerRight.y)) ? Fix2X(trapezoid.lowerLeft.y) : Fix2X(trapezoid.lowerRight.y);
	
	PsychNormalizeRect(resultPsychRect, resultPsychNormRect);
	resultPsychRect[kPsychLeft]=resultPsychNormRect[kPsychLeft] + winRec->textAttributes.textPositionX;
	resultPsychRect[kPsychRight]=resultPsychNormRect[kPsychRight] + winRec->textAttributes.textPositionX;
	resultPsychRect[kPsychTop]=resultPsychNormRect[kPsychTop] + winRec->textAttributes.textPositionY - textHeightToBaseline;
	resultPsychRect[kPsychBottom]=resultPsychNormRect[kPsychBottom] + winRec->textAttributes.textPositionY - textHeightToBaseline;

	PsychCopyOutRectArg(1, FALSE, resultPsychNormRect);
	PsychCopyOutRectArg(2, FALSE, resultPsychRect);


	//release resources
	free((void*)textUniString);
	callError=ATSUDisposeStyle(atsuStyle);

    return(PsychError_none);
}
PsychError SCREENTextBounds(void) 
{
	//for debugging
	TextEncodingBase		textEncodingBase;
	TextEncodingVariant		textEncodingVariant;
	TextEncodingFormat		textEncodingFormat;
	
	///////
        PsychWindowRecordType           *winRec;
	char				*textCString;
	Str255				textPString;
	UniChar				*textUniString;
	OSStatus			callError;
	PsychRectType			resultPsychRect, resultPsychNormRect;
	ATSUTextLayout			textLayout;				//layout is a pointer to an opaque struct.
	int				stringLengthChars;
	int				uniCharBufferLengthElements, uniCharBufferLengthChars, uniCharBufferLengthBytes;
	ByteCount			uniCharStringLengthBytes;
	TextToUnicodeInfo		textToUnicodeInfo;
	TextEncoding			textEncoding;
	ATSUStyle			atsuStyle;
	Boolean				foundFont;
	
	//for ATSU  style attributes
	PsychFontStructPtrType  psychFontRecord;

    			
        //all subfunctions should have these two lines.  
        PsychPushHelp(useString, synopsisString, seeAlsoString);
        if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);};
    
        //check for correct the number of arguments before getting involved
        PsychErrorExit(PsychCapNumInputArgs(2));   	
        PsychErrorExit(PsychRequireNumInputArgs(2)); 	
        PsychErrorExit(PsychCapNumOutputArgs(2));
	
	//get the window pointer and the text string and check that the window record has a font set
        PsychAllocInWindowRecordArg(1, kPsychArgRequired, &winRec);
	foundFont=PsychGetFontRecordFromFontNumber(winRec->textAttributes.textFontNumber, &psychFontRecord);
	if(!foundFont)
		PsychErrorExitMsg(PsychError_user, "Attempt to determine the bounds of text with no font or invalid font number");
		//it would be better to both prevent the user from setting invalid font numbers and init to the OS 9  default font.
	
	//read in the string and get its length and convert it to a unicode string.
	PsychAllocInCharArg(2, kPsychArgRequired, &textCString);
	stringLengthChars=strlen(textCString);
	if(stringLengthChars > 255)
		PsychErrorExitMsg(PsychError_unimplemented, "Cut corners and TextBounds will not accept a string longer than 255 characters");
	CopyCStringToPascal(textCString, textPString);
	uniCharBufferLengthChars= stringLengthChars * CHAR_TO_UNICODE_LENGTH_FACTOR;
	uniCharBufferLengthElements= uniCharBufferLengthChars + 1;		
	uniCharBufferLengthBytes= sizeof(UniChar) * uniCharBufferLengthElements;
	textUniString=(UniChar*)malloc(uniCharBufferLengthBytes);
	//Using a TextEncoding type describe the encoding of the text to be converteed.  
	textEncoding=CreateTextEncoding(kTextEncodingMacRoman, kMacRomanDefaultVariant, kTextEncodingDefaultFormat);
	//Take apart the encoding we just made to check it:
        textEncodingBase=GetTextEncodingBase(textEncoding);
        textEncodingVariant=GetTextEncodingVariant(textEncoding);
        textEncodingFormat=GetTextEncodingFormat(textEncoding);
	//Create a structure holding conversion information from the text encoding type we just created.
	callError=CreateTextToUnicodeInfoByEncoding(textEncoding,&textToUnicodeInfo);
	//Convert the text to a unicode string
	callError=ConvertFromPStringToUnicode(textToUnicodeInfo, textPString, (ByteCount)uniCharBufferLengthBytes,	&uniCharStringLengthBytes,	textUniString);
	//create the text layout object
	callError=ATSUCreateTextLayout(&textLayout);			
	//associate our unicode text string with the text layout object
	callError=ATSUSetTextPointerLocation(textLayout, textUniString, kATSUFromTextBeginning, kATSUToTextEnd, (UniCharCount)stringLengthChars);
	
	//create an ATSU style object
	callError=ATSUCreateStyle(&atsuStyle);
	callError=ATSUClearStyle(atsuStyle);
	
	//Not that we have a style object we have to set style charactersitics.  These include but are more general than Font Manager styles.  
	//ATSU Style objects have three sets of characteristics:  attributes, variations, and features.
	//attributes are things we need to set to match OS 9 behavior, such as the font ID, size, boldness, and italicization.
	//features are esoteric settings which we don't need for reproducing OS 9 behavior.  Whatever clearstyle sets should be fine.
	//font variations are axes of variation through the space of font characteristics.  The font definition includes available axes of variation.  Something else we can ignore for now.  
	PsychSetATSUStyleAttributesFromPsychWindowRecord(atsuStyle, winRec);
	//don't bother to set the variations of the style.
	//don't bother to set the features of the style.
	
	//associate the style with our layout object. This call assigns a style to every character of the string to be displayed.  
	callError=ATSUSetRunStyle(textLayout, atsuStyle, (UniCharArrayOffset)0, (UniCharCount)stringLengthChars);

        //Get the bounds for our text so that and create a texture of sufficient size to containt it. 
        ATSTrapezoid trapezoid;
        ItemCount oActualNumberOfBounds = 0;
        callError=ATSUGetGlyphBounds(textLayout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 0, NULL, &oActualNumberOfBounds);
        if (callError || oActualNumberOfBounds!=1) {
            PsychErrorExitMsg(PsychError_internal, "Failed to compute bounding box in call 1 to ATSUGetGlyphBounds() (nrbounds!=1)\n");    
        }
        callError=ATSUGetGlyphBounds(textLayout, 0, 0, kATSUFromTextBeginning, kATSUToTextEnd, kATSUseDeviceOrigins, 1, &trapezoid, &oActualNumberOfBounds);
        if (callError || oActualNumberOfBounds!=1) {
            PsychErrorExitMsg(PsychError_internal, "Failed to retrieve bounding box in call 2 to ATSUGetGlyphBounds() (nrbounds!=1)\n");    
        }
        
        resultPsychRect[kPsychLeft]=(Fix2X(trapezoid.upperLeft.x) < Fix2X(trapezoid.lowerLeft.x)) ? Fix2X(trapezoid.upperLeft.x) : Fix2X(trapezoid.lowerLeft.x);
        resultPsychRect[kPsychRight]=(Fix2X(trapezoid.upperRight.x) > Fix2X(trapezoid.lowerRight.x)) ? Fix2X(trapezoid.upperRight.x) : Fix2X(trapezoid.lowerRight.x);
        resultPsychRect[kPsychTop]=(Fix2X(trapezoid.upperLeft.y) < Fix2X(trapezoid.upperRight.y)) ? Fix2X(trapezoid.upperLeft.y) : Fix2X(trapezoid.upperRight.y);
        resultPsychRect[kPsychBottom]=(Fix2X(trapezoid.lowerLeft.y) > Fix2X(trapezoid.lowerRight.y)) ? Fix2X(trapezoid.lowerLeft.y) : Fix2X(trapezoid.lowerRight.y);

	PsychNormalizeRect(resultPsychRect, resultPsychNormRect);

	PsychCopyOutRectArg(1, FALSE, resultPsychNormRect);
	PsychCopyOutRectArg(2, FALSE, resultPsychRect);


	//release resources
	free((void*)textUniString);
	callError=ATSUDisposeStyle(atsuStyle);

    return(PsychError_none);
}