//-------------------------------------------------------- void ofVideoPlayer::start(){ //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- if (bLoaded == true && bStarted == false){ SetMovieActive(moviePtr, true); //------------------ set the movie rate to default //------------------ and preroll, so the first frames come correct TimeValue timeNow = GetMovieTime(moviePtr, 0); Fixed playRate = GetMoviePreferredRate(moviePtr); //Not being used! PrerollMovie(moviePtr, timeNow, X2Fix(speed)); SetMovieRate(moviePtr, X2Fix(speed)); setLoopState(OF_LOOP_NORMAL); // get some pixels in there right away: MoviesTask(moviePtr,0); convertPixels(offscreenGWorldPixels, pixels, width, height); bHavePixelsChanged = true; if (bUseTexture == true){ tex.loadData(pixels, width, height, GL_RGB); } bStarted = true; bPlaying = true; } //-------------------------------------- #endif //-------------------------------------- }
//-------------------------------------------------------- void ofQuickTimePlayer::start(){ //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- if (bLoaded == true && bStarted == false){ SetMovieActive(moviePtr, true); //------------------ set the movie rate to default //------------------ and preroll, so the first frames come correct TimeValue timeNow = GetMovieTime(moviePtr, 0); Fixed playRate = GetMoviePreferredRate(moviePtr); //Not being used! PrerollMovie(moviePtr, timeNow, X2Fix(speed)); SetMovieRate(moviePtr, X2Fix(speed)); setLoopState(currentLoopState); // get some pixels in there right away: MoviesTask(moviePtr,0); #if defined(TARGET_OSX) && defined(__BIG_ENDIAN__) convertPixels(offscreenGWorldPixels, pixels.getPixels(), width, height); #endif bHavePixelsChanged = true; bStarted = true; bPlaying = true; } //-------------------------------------- #endif //-------------------------------------- }
//-------------------------------------------------------- void ofVideoPlayer::play(){ //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- if (!bStarted){ start(); }else { // ------------ lower level "startMovie" // ------------ use desired speed & time (-1,1,etc) to Preroll... bPlaying = true; TimeValue timeNow; timeNow = GetMovieTime(moviePtr, nil); PrerollMovie(moviePtr, timeNow, X2Fix(speed)); SetMovieRate(moviePtr, X2Fix(speed)); MoviesTask(moviePtr, 0); } //-------------------------------------- #endif //-------------------------------------- }
void Gosu::drawText(Bitmap& bitmap, const std::wstring& text, int x, int y, Color c, const std::wstring& fontName, unsigned fontHeight, unsigned fontFlags) { if (text.find_first_of(L"\r\n") != std::wstring::npos) throw std::invalid_argument("the argument to drawText cannot contain line breaks"); if (text.empty()) return; CachedFontInfo& font = getFont(fontName); ATSULayoutAndStyle atlas(text, fontName, fontHeight, fontFlags); Rect rect = atlas.textExtents(); unsigned width = rect.right + 1 - rect.left + 1; // add one pixel on OS X std::vector<std::tr1::uint32_t> buf(width * fontHeight); { MacBitmap helper(&buf[0], width, fontHeight); atlas.drawToContext(X2Fix(-rect.left), X2Fix(fontHeight / font.heightAt1Pt * font.descentAt1Pt), helper.context()); } for (unsigned relY = 0; relY < fontHeight; ++relY) for (unsigned relX = 0; relX < width; ++relX) { #ifdef __BIG_ENDIAN__ Color::Channel alpha = buf[relY * width + relX]; #else Color::Channel alpha = Color(buf[relY * width + relX]).alpha(); #endif if (alpha != 0) bitmap.setPixel(x + relX, y + relY, multiply(c, Color(alpha, 0xff, 0xff, 0xff))); } }
//-------------------------------------------------------- void ofQuickTimePlayer::play(){ if( !isLoaded() ){ ofLog(OF_LOG_ERROR, "ofQuickTimePlayer::play - movie not loaded!"); return; } bPlaying = true; bPaused = false; //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- if (!bStarted){ start(); }else { // ------------ lower level "startMovie" // ------------ use desired speed & time (-1,1,etc) to Preroll... TimeValue timeNow; timeNow = GetMovieTime(moviePtr, nil); PrerollMovie(moviePtr, timeNow, X2Fix(speed)); SetMovieRate(moviePtr, X2Fix(speed)); MoviesTask(moviePtr, 0); } //-------------------------------------- #endif //-------------------------------------- //this is if we set the speed first but it only can be set when we are playing. setSpeed(speed); }
//--------------------------------------------------------------------------- void ofVideoPlayer::setPaused(bool _bPause){ bPaused = _bPause; //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- // there might be a more "quicktime-ish" way (or smarter way) // to do this for now, to pause, just set the movie's speed to zero, // on un-pause, set the movie's speed to "speed" // (and hope that speed != 0...) if (bPlaying == true){ if (bPaused == true) SetMovieRate(moviePtr, X2Fix(0)); else SetMovieRate(moviePtr, X2Fix(speed)); } //-------------------------------------- #else //-------------------------------------- gstUtils.setPaused(_bPause); //-------------------------------------- #endif //-------------------------------------- }
//////////////////////////////////////////////////////////////////////////////// // virtual bool LLMediaImplQuickTime::setMovieBoxEnhanced( Rect* rect ) { // get movie rect GetMovieNaturalBoundsRect( mMovieHandle, rect ); int natural_width = ( rect->right - rect->left ); int natural_height = ( rect->bottom - rect->top ); int width = natural_width; int height = natural_height; // if the user has requested a specific size, use it: if ((mMediaRequestedWidth != 0) && (mMediaRequestedHeight != 0)) { width = mMediaRequestedWidth; height = mMediaRequestedHeight; } // if the user has requested, resize media to exactly fit texture if (mAutoScaled) { width = LLMediaManager::textureWidthFromMediaWidth( width ); height = LLMediaManager::textureHeightFromMediaHeight( height ); } // make sure it falls in valid range if ( width < mMinWidth ) width = mMinWidth; if ( width > mMaxWidth ) width = mMaxWidth; if ( height < mMinHeight ) height = mMinHeight; if ( height > mMaxHeight ) height = mMaxHeight; // scale movie to fit rect and invert vertically to match opengl image format MatrixRecord transform; SetIdentityMatrix( &transform ); // transforms are additive so start from identify matrix double scaleX = (double) width / natural_width; double scaleY = -1.0 * (double) height / natural_height; double centerX = width / 2.0; double centerY = height / 2.0; ScaleMatrix( &transform, X2Fix ( scaleX ), X2Fix ( scaleY ), X2Fix ( centerX ), X2Fix ( centerY ) ); SetMovieMatrix( mMovieHandle, &transform ); // return the new rect rect->right = width; rect->bottom = height; rect->left = 0; rect->top = 0; return true; }
OSStatus ATSUStyleSetFontIDAndSize(ATSUStyle iStyle, ATSUFontID fid, float fsize) { ATSUAttributeTag tags[2] = {kATSUFontTag, kATSUSizeTag}; Fixed ffsize = X2Fix(fsize); ByteCount counts[2] = {sizeof(ATSUFontID*), sizeof(Fixed*)}; ATSUAttributeValuePtr vals[2] = {&fid, &ffsize}; return ATSUSetAttributes( iStyle, 2, tags, counts, vals); }
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; }
//--------------------------------------------------------------------------- void ofVideoPlayer::setFrame(int frame){ //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- // frame 0 = first frame... // this is the simple way... //float durationPerFrame = getDuration() / getTotalNumFrames(); // seems that freezing, doing this and unfreezing seems to work alot // better then just SetMovieTimeValue() ; if (!bPaused) SetMovieRate(moviePtr, X2Fix(0)); // this is better with mpeg, etc: double frameRate = 0; double movieTimeScale = 0; MovieGetStaticFrameRate(moviePtr, &frameRate); movieTimeScale = GetMovieTimeScale(moviePtr); if (frameRate > 0){ double frameDuration = 1 / frameRate; TimeValue t = (TimeValue)(frame * frameDuration * movieTimeScale); SetMovieTimeValue(moviePtr, t); MoviesTask(moviePtr, 0); } if (!bPaused) SetMovieRate(moviePtr, X2Fix(speed)); //-------------------------------------- #else //-------------------------------------- gstUtils.setFrame(frame); //-------------------------------------- #endif //-------------------------------------- }
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; }
//------------------------------------------------------------ void ofQuicktimeSoundPlayer::setSpeed(float spd){ if (getIsPlaying() == true){ if (fabs(spd - 0) < FLT_EPSILON){ bIWasPlayingAndMySpeedWasSetToZero = true; } else { bIWasPlayingAndMySpeedWasSetToZero = false; } SetMovieRate(soundToPlay, X2Fix(spd)); } speed = spd; }
A2(PUBLIC, Fixed, FixATan2, LONGINT, x, LONGINT, y) /* IMIV-65 */ { Extended z; if (y == 0) { if (x & 0x80000000) /*-->*/ return x & 0x7FFFFFFF ? 205888 : 234019; /* trial and error */ /*-->*/ return 0; } z = atan2((double) y, (double) x); return X2Fix(&z); }
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; }
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; }
//--------------------------------------------------------------------------- void ofVideoPlayer::setSpeed(float _speed){ speed = _speed; //-------------------------------------- #ifdef OF_VIDEO_PLAYER_QUICKTIME //-------------------------------------- if (bPlaying == true){ //setMovieRate actually plays, so let's call it only when we are playing SetMovieRate(moviePtr, X2Fix(speed)); } //-------------------------------------- #endif //-------------------------------------- }
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; }
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; }
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; }
void* loadAATfont(ATSFontRef fontRef, long scaled_size, const char* cp1) { ATSUFontID fontID = FMGetFontFromATSFontRef(fontRef); ATSUStyle style = 0; OSStatus status = ATSUCreateStyle(&style); float extend = 1.0; float slant = 0.0; float embolden = 0.0; float letterspace = 0.0; int i; if (status == noErr) { UInt32 rgbValue; Fixed tracking = 0x80000000; Fixed atsuSize = FixedTeXtoPSPoints(scaled_size); ATSStyleRenderingOptions options = kATSStyleNoHinting; Fract hangInhibit = fract1; ATSUAttributeTag tags[] = { kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag, kATSUHangingInhibitFactorTag }; ByteCount sizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(ATSStyleRenderingOptions), sizeof(Fract) }; ATSUAttributeValuePtr attrs[] = { &fontID, &atsuSize, &options, &hangInhibit }; ATSUSetAttributes(style, sizeof(tags) / sizeof(ATSUAttributeTag), tags, sizes, attrs); #define FEAT_ALLOC_CHUNK 8 #define VAR_ALLOC_CHUNK 4 if (cp1 != NULL) { int allocFeats = FEAT_ALLOC_CHUNK; UInt16* featureTypes = (UInt16*)xmalloc(allocFeats * sizeof(UInt16)); UInt16* selectorValues = (UInt16*)xmalloc(allocFeats * sizeof(UInt16)); int numFeatures = 0; int allocVars = VAR_ALLOC_CHUNK; UInt32* axes = (UInt32*)xmalloc(allocVars * sizeof(UInt32)); SInt32* values = (SInt32*)xmalloc(allocVars * sizeof(SInt32)); int numVariations = 0; // interpret features & variations following ":" while (*cp1) { // locate beginning of name=value pair if (*cp1 == ':' || *cp1 == ';') // skip over separator ++cp1; while (*cp1 == ' ' || *cp1 == '\t') // skip leading whitespace ++cp1; if (*cp1 == 0) // break if end of string break; // scan to end of pair const char* cp2 = cp1; while (*cp2 && *cp2 != ';' && *cp2 != ':') ++cp2; // look for the '=' separator const char* cp3 = cp1; while (cp3 < cp2 && *cp3 != '=') ++cp3; if (cp3 == cp2) goto bad_option; // now cp1 points to option name, cp3 to '=', cp2 to ';' or null // first try for a feature by this name ATSUFontFeatureType featureType; featureType = find_feature_by_name(fontID, cp1, cp3 - cp1); if (featureType != 0x0000FFFF) { // look past the '=' separator for setting names int featLen = cp3 - cp1; ++cp3; while (cp3 < cp2) { // skip leading whitespace while (*cp3 == ' ' || *cp3 == '\t') ++cp3; // possibly multiple settings... int disable = 0; if (*cp3 == '!') { // check for negation disable = 1; ++cp3; } // scan for end of setting name const char* cp4 = cp3; while (cp4 < cp2 && *cp4 != ',') ++cp4; // now cp3 points to name, cp4 to ',' or ';' or null ATSUFontFeatureSelector selectorValue = find_selector_by_name(fontID, featureType, cp3, cp4 - cp3); if (selectorValue != 0x0000FFFF) { if (numFeatures == allocFeats) { allocFeats += FEAT_ALLOC_CHUNK; featureTypes = xrealloc(featureTypes, allocFeats * sizeof(UInt16)); selectorValues = xrealloc(selectorValues, allocFeats * sizeof(UInt16)); } featureTypes[numFeatures] = featureType; selectorValues[numFeatures] = selectorValue + disable; ++numFeatures; } else { fontfeaturewarning(cp1, featLen, cp3, cp4 - cp3); } // point beyond setting name terminator cp3 = cp4 + 1; } goto next_option; } // try to find a variation by this name ATSUFontVariationAxis axis; axis = find_axis_by_name(fontID, cp1, cp3 - cp1); if (axis != 0) { // look past the '=' separator for the value ++cp3; double value = 0.0, decimal = 1.0; bool negate = false; if (*cp3 == '-') { ++cp3; negate = true; } while (cp3 < cp2) { int v = *cp3 - '0'; if (v >= 0 && v <= 9) { if (decimal != 1.0) { value += v / decimal; decimal *= 10.0; } else value = value * 10.0 + v; } else if (*cp3 == '.') { if (decimal != 1.0) break; decimal = 10.0; } else break; ++cp3; } if (negate) value = -value; if (numVariations == allocVars) { allocVars += VAR_ALLOC_CHUNK; axes = xrealloc(axes, allocVars * sizeof(UInt32)); values = xrealloc(values, allocVars * sizeof(SInt32)); } axes[numVariations] = axis; values[numVariations] = value * 65536.0; // X2Fix(value); ++numVariations; goto next_option; } // didn't find feature or variation, try other options.... i = readCommonFeatures(cp1, cp2, &extend, &slant, &embolden, &letterspace, &rgbValue); if (i == 1) goto next_option; else if (i == -1) goto bad_option; if (strncmp(cp1, "tracking", 8) == 0) { cp3 = cp1 + 8; if (*cp3 != '=') goto bad_option; ++cp3; double val = read_double(&cp3); tracking = X2Fix(val); goto next_option; } bad_option: // not a name=value pair, or not recognized.... // check for plain "vertical" before complaining if (strncmp(cp1, "vertical", 8) == 0) { cp3 = cp2; if (*cp3 == ';' || *cp3 == ':') --cp3; while (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t') --cp3; if (*cp3) ++cp3; if (cp3 == cp1 + 8) { ATSUVerticalCharacterType vert = kATSUStronglyVertical; tags[0] = kATSUVerticalCharacterTag; sizes[0] = sizeof(ATSUVerticalCharacterType); attrs[0] = | ATSUSetAttributes(style, 1, tags, sizes, attrs); goto next_option; } } fontfeaturewarning(cp1, cp2 - cp1, 0, 0); next_option: // go to next name=value pair cp1 = cp2; } if (numFeatures > 0) ATSUSetFontFeatures(style, numFeatures, featureTypes, selectorValues); if (numVariations > 0) ATSUSetVariations(style, numVariations, axes, values); if ((loadedfontflags & FONT_FLAGS_COLORED) != 0) { ATSURGBAlphaColor rgba; rgba.red = ((rgbValue & 0xFF000000) >> 24) / 255.0; rgba.green = ((rgbValue & 0x00FF0000) >> 16) / 255.0; rgba.blue = ((rgbValue & 0x0000FF00) >> 8 ) / 255.0; rgba.alpha = ((rgbValue & 0x000000FF) ) / 255.0; tags[0] = kATSURGBAlphaColorTag; sizes[0] = sizeof(ATSURGBAlphaColor); attrs[0] = &rgba; ATSUSetAttributes(style, 1, tags, sizes, attrs); }
static inline Fixed FixedTeXtoPSPoints(Fixed pts) { return X2Fix(TeXtoPSPoints(Fix2X(pts))); }
static inline Fixed FixedPStoTeXPoints(Fixed pts) { return X2Fix(PStoTeXPoints(Fix2X(pts))); }
//------------------------------------------------------------------------ ATSUTextLayout nsATSUIToolkit::GetTextLayout(short aFontNum, short aSize, PRBool aBold, PRBool aItalic, nscolor aColor) { ATSUTextLayout txLayout = nsnull; OSStatus err; if (nsATSUIUtils::gTxLayoutCache->Get(aFontNum, aSize, aBold, aItalic, aColor, &txLayout)) return txLayout; UniChar dmy[1]; err = ::ATSUCreateTextLayoutWithTextPtr (dmy, 0,0,0,0,NULL, NULL, &txLayout); if(noErr != err) { NS_WARNING("ATSUCreateTextLayoutWithTextPtr failed"); // goto errorDone; return nsnull; } ATSUStyle theStyle; err = ::ATSUCreateStyle(&theStyle); if(noErr != err) { NS_WARNING("ATSUCreateStyle failed"); // goto errorDoneDestroyTextLayout; err = ::ATSUDisposeTextLayout(txLayout); return nsnull; } ATSUAttributeTag theTag[ATTR_CNT]; ByteCount theValueSize[ATTR_CNT]; ATSUAttributeValuePtr theValue[ATTR_CNT]; //--- Font ID & Face ----- ATSUFontID atsuFontID; // The use of ATSUFONDtoFontID is not recommended, see // http://developer.apple.com/documentation/Carbon/Reference/ATSUI_Reference/atsu_reference_Reference/chapter_1.2_section_19.html FMFontStyle fbStyle; if (::FMGetFontFromFontFamilyInstance(aFontNum, 0, &atsuFontID, &fbStyle) == kFMInvalidFontErr) { NS_WARNING("FMGetFontFromFontFamilyInstance failed"); // goto errorDoneDestroyStyle; err = ::ATSUDisposeStyle(theStyle); err = ::ATSUDisposeTextLayout(txLayout); return nsnull; } theTag[0] = kATSUFontTag; theValueSize[0] = (ByteCount) sizeof(ATSUFontID); theValue[0] = (ATSUAttributeValuePtr) &atsuFontID; //--- Font ID & Face ----- //--- Size ----- float dev2app; short fontsize = aSize; dev2app = mContext->DevUnitsToAppUnits(); // Fixed size = FloatToFixed( roundf(float(fontsize) / dev2app)); Fixed size = FloatToFixed( (float) rint(float(fontsize) / dev2app)); if( FixRound ( size ) < 9 && !nsFontUtils::DisplayVerySmallFonts()) size = X2Fix(9); theTag[1] = kATSUSizeTag; theValueSize[1] = (ByteCount) sizeof(Fixed); theValue[1] = (ATSUAttributeValuePtr) &size; //--- Size ----- //--- Color ----- RGBColor color; #define COLOR8TOCOLOR16(color8) ((color8 << 8) | color8) color.red = COLOR8TOCOLOR16(NS_GET_R(aColor)); color.green = COLOR8TOCOLOR16(NS_GET_G(aColor)); color.blue = COLOR8TOCOLOR16(NS_GET_B(aColor)); theTag[2] = kATSUColorTag; theValueSize[2] = (ByteCount) sizeof(RGBColor); theValue[2] = (ATSUAttributeValuePtr) &color; //--- Color ----- //--- Bold ----- Boolean isBold = aBold ? true : false; theTag[3] = kATSUQDBoldfaceTag; theValueSize[3] = (ByteCount) sizeof(Boolean); theValue[3] = (ATSUAttributeValuePtr) &isBold; //--- Bold ----- //--- Italic ----- Boolean isItalic = aItalic ? true : false; theTag[4] = kATSUQDItalicTag; theValueSize[4] = (ByteCount) sizeof(Boolean); theValue[4] = (ATSUAttributeValuePtr) &isItalic; //--- Italic ----- err = ::ATSUSetAttributes(theStyle, ATTR_CNT, theTag, theValueSize, theValue); if(noErr != err) { NS_WARNING("ATSUSetAttributes failed"); // goto errorDoneDestroyStyle; err = ::ATSUDisposeStyle(theStyle); err = ::ATSUDisposeTextLayout(txLayout); return nsnull; } err = ::ATSUSetRunStyle(txLayout, theStyle, kATSUFromTextBeginning, kATSUToTextEnd); if(noErr != err) { NS_WARNING("ATSUSetRunStyle failed"); // goto errorDoneDestroyStyle; err = ::ATSUDisposeStyle(theStyle); err = ::ATSUDisposeTextLayout(txLayout); return nsnull; } err = ::ATSUSetTransientFontMatching(txLayout, true); if(noErr != err) { NS_WARNING( "ATSUSetTransientFontMatching failed"); // goto errorDoneDestroyStyle; err = ::ATSUDisposeStyle(theStyle); err = ::ATSUDisposeTextLayout(txLayout); return nsnull; } nsATSUIUtils::gTxLayoutCache->Set(aFontNum, aSize, aBold, aItalic, aColor, txLayout); return txLayout; }
bool LLMediaImplQuickTime::processState() { // start stream if ( nextCommand() == LLMediaBase::COMMAND_START ) { // valid when we are in these states if ( getStatus() == LLMediaBase::STATUS_NAVIGATING|| getStatus() == LLMediaBase::STATUS_STOPPED || getStatus() == LLMediaBase::STATUS_PAUSED ) { // it appears that the movie must be in a loaded state before we do this command if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) { MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)GetMoviePreferredRate( mMovieHandle ) ); MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume ); setStatus( LLMediaBase::STATUS_STARTED ); clearCommand(); } } } else if ( nextCommand() == LLMediaBase::COMMAND_STOP ) { // valid when we are in these states if ( getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STARTED || getStatus() == LLMediaBase::STATUS_PAUSED ) { // it appears that the movie must be in a loaded state before we do this command if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) { // stop playing Fixed rate = X2Fix( 0.0 ); MCDoAction( mMovieController, mcActionPlay, (void*)rate ); // go back to start rewind(); setStatus( LLMediaBase::STATUS_STOPPED ); clearCommand(); }; }; } else if ( nextCommand() == LLMediaBase::COMMAND_PAUSE ) { // valid when we are in these states if ( getStatus() == LLMediaBase::STATUS_NAVIGATING || getStatus() == LLMediaBase::STATUS_STARTED || getStatus() == LLMediaBase::STATUS_STOPPED ) { // it appears that the movie must be in a loaded state before we do this command if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK ) { // stop playing Fixed rate = X2Fix( 0.0 ); MCDoAction( mMovieController, mcActionPlay, (void*)rate ); setStatus( LLMediaBase::STATUS_PAUSED ); clearCommand(); }; }; }; return true; }
static int mac_open(register gx_device *dev) { gx_device_macos * mdev = (gx_device_macos *)dev; static short picHeader[42] = { 0x0000, // picture size 0x0000, 0x0000, 0x0318, 0x0264, // bounding rect at 72dpi 0x0011, 0x02ff, 0x0c00, 0xfffe, 0x0000, // version/header opcodes 0x0048, 0x0000, // best x resolution 0x0048, 0x0000, // best y resolution 0x0000, 0x0000, 0x0318, 0x0264, // optimal src rect at 72dpi 0x0000, // reserved 0x0000, 0x001e, // DefHilite 0x0008, 0x0048, // PenMode 0x001a, 0x0000, 0x0000, 0x0000, // RGBFgCol = Black 0x001b, 0xFFFF, 0xFFFF, 0xFFFF, // RGBBkCol = White 0x0001, 0x000A, // set clipping 0x0000, 0x0000, 0x0318, 0x0264, // clipping rect 0x0032, 0x0000, 0x0000, 0x0318, 0x0264 // erase rect }; mac_set_colordepth(dev, mdev->color_info.depth); mdev->numUsedFonts = 0; mdev->lastFontFace = -1; mdev->lastFontSize = -1; mdev->lastFontID = -1; mdev->pic = (PicHandle) NewHandle(500000); if (mdev->pic == 0) // error, not enough memory return gs_error_VMerror; HLockHi((Handle) mdev->pic); // move handle high and lock it mdev->currPicPos = (short*) *mdev->pic; memcpy(mdev->currPicPos, picHeader, 42*2); mdev->currPicPos += 42; // enter correct dimensions and resolutions ((short*)(*mdev->pic))[ 3] = mdev->MediaSize[1]; ((short*)(*mdev->pic))[ 4] = mdev->MediaSize[0]; ((short*)(*mdev->pic))[16] = ((short*)(*mdev->pic))[35] = ((short*)(*mdev->pic))[40] = mdev->height; ((short*)(*mdev->pic))[17] = ((short*)(*mdev->pic))[36] = ((short*)(*mdev->pic))[41] = mdev->width; ((short*)(*mdev->pic))[10] = (((long) X2Fix( mdev->x_pixels_per_inch )) & 0xFFFF0000) >> 16; ((short*)(*mdev->pic))[11] = ((long) X2Fix( mdev->x_pixels_per_inch )) & 0x0000FFFF; ((short*)(*mdev->pic))[12] = (((long) X2Fix( mdev->y_pixels_per_inch )) & 0xFFFF0000) >> 16; ((short*)(*mdev->pic))[13] = ((long) X2Fix( mdev->y_pixels_per_inch )) & 0x0000FFFF; // finish picture, but dont increment pointer, we want to go on drawing *mdev->currPicPos = 0x00ff; // notify the caller that a new device was opened if (pgsdll_callback) (*pgsdll_callback) (GSDLL_DEVICE, (char *)mdev, 1); return 0; }
/* that's why this will only work on a fully white background!!!! */ static int mac_copy_alpha(gx_device *dev, const unsigned char *base, int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h, gx_color_index color, int depth) { gx_device_macos * mdev = (gx_device_macos *)dev; ColorSpec *colorTable; short copyMode, shade, maxShade = (1 << depth) - 1, byteCount = raster * h; gx_color_value rgb[3]; colorHSV colHSV; colorRGB colRGB; float saturation, value; fit_copy(dev, base, data_x, raster, id, x, y, w, h); CheckMem( byteCount*4 + 200*1024, byteCount*4 + 500*1024 ); ResetPage(); colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (maxShade+1)); if (colorTable == NULL) return gs_error_VMerror; (*dev_proc(dev, map_color_rgb))(dev, color, rgb); colRGB.red = rgb[0]; colRGB.green = rgb[1]; colRGB.blue = rgb[2]; mac_convert_rgb_hsv(&colRGB, &colHSV); saturation = colHSV.s; value = colHSV.v; for (shade=0; shade <= maxShade; shade++) { colorTable[shade].value = maxShade - shade; colHSV.s = saturation * (1.0 - (float)shade/(float)maxShade); colHSV.v = value + ((1.0 - value) * (float)shade/(float)maxShade); mac_convert_hsv_rgb(&colHSV, &colRGB); colorTable[shade].rgb.red = colRGB.red; colorTable[shade].rgb.green = colRGB.green; colorTable[shade].rgb.blue = colRGB.blue; } copyMode = srcCopy + ditherCopy; GSSetStdCol(mdev->currPicPos); if (raster < 8) { PICTWriteOpcode(mdev->currPicPos, 0x0090); } else { PICTWriteOpcode(mdev->currPicPos, 0x0098); } PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/depth, h, raster, 0, 0, X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), depth); PICTWriteColorTable(mdev->currPicPos, 0, maxShade+1, colorTable); PICTWriteRect(mdev->currPicPos, data_x, 0, w, h); PICTWriteRect(mdev->currPicPos, x, y, w, h); PICTWriteInt(mdev->currPicPos, copyMode); PICTWriteDataPackBits(mdev->currPicPos, base, raster, h); PICT_OpEndPicGoOn(mdev->currPicPos); free(colorTable); return 0; }
/* Copy a color bitmap. */ static int mac_copy_color (register gx_device *dev, const unsigned char *base, int data_x, int raster, gx_bitmap_id id, int x, int y, int w, int h) { gx_device_macos * mdev = (gx_device_macos *)dev; int byteCount = raster * h, color; gx_color_value rgb[3]; fit_copy(dev, base, data_x, raster, id, x, y, w, h); CheckMem(10*1024 + byteCount*4, 100*1024 + byteCount*4); ResetPage(); GSSetStdCol(mdev->currPicPos); // Sets FgCol to Black and BkCol to White if (mdev->color_info.depth == 24) { PICTWriteOpcode(mdev->currPicPos, 0x009A); PICTWriteLong(mdev->currPicPos, 0x000000FF); PICTWritePixMap(mdev->currPicPos, 0, 0, raster/4, h, raster, 2, 0, X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), 32); PICTWriteRect(mdev->currPicPos, data_x, 0, w, h); PICTWriteRect(mdev->currPicPos, x, y, w, h); PICTWriteInt(mdev->currPicPos, srcCopy); /* memcpy(mdev->currPicPos, base, byteCount); (char*)(mdev->currPicPos) += byteCount;*/ { short i; byteCount = 0; for (i=0; i<raster/4*h; i++) { // PICTWriteByte(mdev->currPicPos, 0x00); PICTWriteByte(mdev->currPicPos, 0x00); PICTWriteByte(mdev->currPicPos, 0x00); PICTWriteByte(mdev->currPicPos, 0x00); byteCount += 3; } } if (byteCount % 2) PICTWriteFillByte(mdev->currPicPos); } else if (mdev->color_info.depth <= 8) { ColorSpec *colorTable; colorTable = (ColorSpec*) malloc(sizeof(ColorSpec) * (1 << mdev->color_info.depth)); for (color=0; color < (1 << mdev->color_info.depth); color++) { (*dev_proc(dev, map_color_rgb))(dev, color, rgb); colorTable[color].value = color; colorTable[color].rgb.red = rgb[0]; colorTable[color].rgb.green = rgb[1]; colorTable[color].rgb.blue = rgb[2]; } PICTWriteOpcode(mdev->currPicPos, 0x0098); PICTWritePixMap(mdev->currPicPos, 0, 0, raster*8/mdev->color_info.depth, h, raster, 1, 0, X2Fix(mdev->x_pixels_per_inch), X2Fix(mdev->y_pixels_per_inch), mdev->color_info.depth); PICTWriteColorTable(mdev->currPicPos, 0, (1 << mdev->color_info.depth), colorTable); PICTWriteRect(mdev->currPicPos, data_x, 0, w, h); PICTWriteRect(mdev->currPicPos, x, y, w, h); PICTWriteInt(mdev->currPicPos, srcCopy); PICTWriteDataPackBits(mdev->currPicPos, base, raster, h); free(colorTable); } else { gx_default_copy_color( dev, base, data_x, raster, id, x, y, w, h ); } PICT_OpEndPicGoOn(mdev->currPicPos); return 0; }
GLuint platformLoadTextureFile(string theFilename, bool generateMipmaps, int *width, int *height) { #ifdef QuickTimeInstalled GLuint textureName; // the "name" by which OpenGL knows the texture unsigned char *pImageBuffer; // the buffer that contains the image data GWorldPtr pGWorld; // a gworld to load the image into int imageDepth; FSSpec fsspecImage; // FSSpec of the image to load #ifdef __APPLE__ CFURLRef imageURL; FSRef imagefsRef; #endif OSStatus err = noErr; // err return value long rowStride; // length, in bytes, of a pixel row in the image GraphicsImportComponent giComp; // component for importing image MatrixRecord matrix; Rect rectImage; // rectangle of source image PixMapHandle hPixMap; // handle to image pix map ImageDescriptionHandle hImageDesc; // handle to image description used to get image depth long imageWidth; long imageHeight; float imageAspect; long textureWidth; long textureHeight; // get the full path to the texture file string fileLocation; fileLocation = pathToResourceDirectory() + theFilename; #ifdef __APPLE__ // create a URL to the file from the C string imageURL = CFURLCreateWithBytes (kCFAllocatorDefault, (UInt8 *)fileLocation.c_str(), fileLocation.length(), kCFStringEncodingASCII, NULL); if (imageURL == NULL) { cout << "error getting URL for image file (image file may not exist): " << theFilename << endl; return 0; } // get a FSRef from the URL if (!CFURLGetFSRef(imageURL, &imagefsRef)) { cout << "error getting FSRef for image file:: " << theFilename << endl; CFRelease(imageURL); return 0; } // get the FSSpec from the FSRef if (FSGetCatalogInfo (&imagefsRef, kFSCatInfoNone, NULL, NULL, &fsspecImage, NULL)) { cout << "error getting FSSpec for image file: " << theFilename << endl; CFRelease(imageURL); return 0; } // release the URL (not needed any more) CFRelease(imageURL); #endif #ifdef _WIN32 // get an FSSpec from the pathname if (NativePathNameToFSSpec ((char *)fileLocation.c_str(), &fsspecImage, kErrorIfFileNotFound)) { cout << "error getting FSSpec for image file: " << fileLocation << endl; return 0; } #endif // save the onscreen graphics port GDHandle origDevice; CGrafPtr origPort; GetGWorld (&origPort, &origDevice); // get an importer for the file err = GetGraphicsImporterForFileWithFlags (&fsspecImage, &giComp, kDontUseValidateToFindGraphicsImporter); if (err != noErr) return 0; // get the image bounds err = GraphicsImportGetNaturalBounds (giComp, &rectImage); if (err != noErr) return 0; // create a handle for the image description and lock it hImageDesc = (ImageDescriptionHandle) NewHandle (sizeof (ImageDescriptionHandle)); HLock ((Handle) hImageDesc); // retrieve the image description err = GraphicsImportGetImageDescription (giComp, &hImageDesc); if (err != noErr) return 0; // find width and height imageWidth = (int) (rectImage.right - rectImage.left); imageHeight = (int) (rectImage.bottom - rectImage.top); // now calculate the aspect ratio (width/height), used to restore image correctly imageAspect = ((float) imageWidth) / ((float) imageHeight); // get the image's pixel depth imageDepth = (**hImageDesc).depth; // find nearest acceptable texture size (width and height) for the image textureWidth = GetTextureDimFromImageDim (imageWidth); textureHeight = GetTextureDimFromImageDim (imageHeight); // pass the optimised (and scaled) size back out to the caller *width = textureWidth; *height = textureHeight; // set texture rectangle for creation of GWorld #ifdef __APPLE__ SetRect (&rectImage, 0, 0, (int) textureWidth, (int) textureHeight); #endif #ifdef _WIN32 MacSetRect (&rectImage, 0, 0, (int) textureWidth, (int) textureHeight); #endif // set stride in bytes width of image * 4 bytes per pixel rowStride = textureWidth * 4; // build new buffer exact size of image (stride * height) pImageBuffer = (unsigned char *) NewPtr (rowStride * textureHeight); // check we got the buffer we wanted if (pImageBuffer == NULL) { // failed - release the component and return an error CloseComponent(giComp); return 0; } // create a new gworld using our unpadded buffer, setting the pixel type correctly for the expected image depth #ifdef __BIG_ENDIAN__ QTNewGWorldFromPtr (&(pGWorld), k32ARGBPixelFormat, &rectImage, NULL, NULL, 0, pImageBuffer, rowStride); #else QTNewGWorldFromPtr (&(pGWorld), k32RGBAPixelFormat, &rectImage, NULL, NULL, 0, pImageBuffer, rowStride); #endif // could we allocate the GWorld? if (pGWorld == NULL) { // failed - release the buffer, component and return an error DisposePtr ((Ptr) pImageBuffer); CloseComponent(giComp); return 0; } // build a transformation matrix to scale the image to the texture size // this also flips the image horizontally, so that texture coordinates map correctly float horizontalScale = (float) textureWidth / (float) imageWidth; float verticalScale = (float) textureHeight / (float) imageHeight; SetIdentityMatrix (&matrix); ScaleMatrix (&matrix, X2Fix(horizontalScale), X2Fix(-verticalScale), 0, 0); TranslateMatrix (&matrix, 0, X2Fix((float)textureHeight)); // set the matrix as the importer matrix err = GraphicsImportSetMatrix(giComp, &matrix); // set the destination of the importer component if (err == noErr) err = GraphicsImportSetGWorld (giComp, pGWorld, NULL); // ensure lossless decompression (if the CODEC supports this) if (err == noErr) err = GraphicsImportSetQuality(giComp, codecLosslessQuality); if (err != noErr) { // failed - release the GWorld, buffer, component and return an error DisposeGWorld (pGWorld); DisposePtr ((Ptr) pImageBuffer); CloseComponent(giComp); return 0; } // get the address of the GWorld's pixmap hPixMap = GetGWorldPixMap (pGWorld); // if everything looks good draw the image to the locked pixmap if ((hPixMap) && (LockPixels (hPixMap))) GraphicsImportDraw (giComp); else { // the pixmap doesn't exist, or we couldn't lock it // release the GWorld, buffer, component and return an error DisposeGWorld (pGWorld); DisposePtr ((Ptr) pImageBuffer); CloseComponent(giComp); return 0; } // for images without an alpha channel, initialise the alpha bytes since QuickTime won't if (imageDepth < 32) { #ifdef __BIG_ENDIAN__ for( unsigned char *p = pImageBuffer; p < pImageBuffer + (rowStride * textureHeight); p+=4) *p = 0xFF; #else for( unsigned char *p = pImageBuffer+3; p < pImageBuffer + (rowStride * textureHeight) +3; p+=4) *p = 0xFF; #endif } // unlock the pixmap UnlockPixels (hPixMap); // dump the component CloseComponent(giComp); // set image width in groups (pixels), accounts for border this ensures proper image alignment row to row glPixelStorei (GL_UNPACK_ROW_LENGTH, textureWidth); // generate a "name" for the texture glGenTextures (1, &textureName); // create the texture in OpenGL glBindTexture(GL_TEXTURE_2D, textureName); // tell OpenGL about the texture and have GLU build mipmaps #ifdef __BIG_ENDIAN__ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pImageBuffer); #else glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pImageBuffer); #endif if (generateMipmaps) #ifdef __BIG_ENDIAN__ if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, textureWidth, textureHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pImageBuffer) != 0) #else if (gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE, pImageBuffer) != 0) #endif // good time to check for errors? openGLCheckError(); // finished with the GWorld but not the image buffer (it's used by OpenGL as the "live" image buffer) DisposeGWorld (pGWorld); // restore the current graphics port we saved earlier SetGWorld(origPort, origDevice); // all done - return the texture name return textureName; #endif // QuickTimeInstalled }
// 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); }
GWorldPtr OpenImage (void) { unsigned long rowStride; GraphicsImportComponent giComp; NavReplyRecord replyNav; NavTypeListHandle hTypeList = (NavTypeListHandle) NewHandleClear (sizeof (NavTypeList) + sizeof (OSType) * 13); FSSpec fsspecImage; AEKeyword theKeyword; DescType actualType; Size actualSize; OSStatus err = noErr; Rect rectImage; GDHandle origDevice; CGrafPtr origPort; PixMapHandle hPixMap; ImageDescriptionHandle hImageDesc; MatrixRecord matrix; GWorldPtr pGWorld; unsigned char * pImageBuffer; long imageWidth; long imageHeight; float imageAspect; long imageDepth; long textureWidth; long textureHeight; GetGWorld (&origPort, &origDevice); // save onscreen graphics port HLock ((Handle) hTypeList); (**hTypeList).osTypeCount = 14; (**hTypeList).osType[0] = 'qtif'; (**hTypeList).osType[1] = 'SGI '; (**hTypeList).osType[2] = '8BPS'; (**hTypeList).osType[3] = 'GIF '; (**hTypeList).osType[4] = 'GIFf'; (**hTypeList).osType[5] = 'JPEG'; (**hTypeList).osType[6] = 'JPG '; (**hTypeList).osType[7] = 'PICT'; (**hTypeList).osType[8] = 'PNTG'; (**hTypeList).osType[9] = 'grip'; (**hTypeList).osType[10] = 'BMPp'; (**hTypeList).osType[11] = 'TIFF'; (**hTypeList).osType[12] = 'TEXT'; (**hTypeList).osType[13] = '????'; err = NavChooseFile (NULL, &replyNav, NULL, NULL, NULL, NULL, hTypeList, NULL); if ((err == noErr) && (replyNav.validRecord)) err = AEGetNthPtr (&(replyNav.selection), 1, typeFSS, &theKeyword, &actualType, &fsspecImage, sizeof (fsspecImage), &actualSize); NavDisposeReply (&replyNav); if (err != noErr) return NULL; GetGraphicsImporterForFile (&fsspecImage, &giComp); if (err != noErr) return NULL; // create GWorld err = GraphicsImportGetNaturalBounds (giComp, &rectImage); if (err != noErr) return NULL; hImageDesc = (ImageDescriptionHandle) NewHandle (sizeof (ImageDescriptionHandle)); HLock ((Handle) hImageDesc); err = GraphicsImportGetImageDescription (giComp, &hImageDesc); if (err != noErr) return NULL; imageWidth = rectImage.right - rectImage.left; imageHeight = rectImage.bottom - rectImage.top; imageAspect = ((float) imageWidth) / ((float) imageHeight); imageDepth = (**hImageDesc).depth; // bits if (imageDepth <= 16) imageDepth = 16; else imageDepth = 32; #if 1 textureWidth = imageWidth;//40;//imageWidth;//256; textureHeight = imageHeight;//40 * imageHeight / imageWidth;//imageHeight;//256; #else textureWidth = imageWidth;//256; textureHeight = imageHeight;//256; #endif SetRect (&rectImage, 0, 0, textureWidth, textureHeight); // l, t, r. b reset to texture rectangle rowStride = textureWidth * imageDepth / 8; pImageBuffer = (unsigned char *) NewPtrClear (rowStride * (textureHeight)); if (imageDepth == 32) QTNewGWorldFromPtr (&(pGWorld), k32ARGBPixelFormat, &rectImage, NULL, NULL, 0, pImageBuffer, rowStride); else QTNewGWorldFromPtr (&(pGWorld), k16BE555PixelFormat, &rectImage, NULL, NULL, 0, pImageBuffer, rowStride); if (NULL == pGWorld) return NULL; // decompress to gworld SetIdentityMatrix (&matrix); ScaleMatrix (&matrix, X2Fix ((float) textureWidth / (float) imageWidth), X2Fix ((float) textureHeight / (float) imageHeight), X2Fix (0.0), X2Fix (0.0)); err = GraphicsImportSetMatrix(giComp, &matrix); if (err != noErr) return NULL; err = GraphicsImportSetGWorld (giComp, pGWorld, NULL); if (err != noErr) return NULL; err = GraphicsImportSetQuality(giComp, codecLosslessQuality); if (err != noErr) return NULL; hPixMap = GetGWorldPixMap (pGWorld); if ((hPixMap) && (LockPixels (hPixMap))) // lock offscreen pixel map GraphicsImportDraw (giComp); else return NULL; // modify alpha if ( imageDepth == 32 ) { unsigned long i; unsigned long * pixel = (unsigned long *)GetPixBaseAddr( hPixMap ); for (i = 0; i < textureWidth * textureHeight; i++) { if ((*pixel & 0x00FFFFFF) == 0x00FF00) // mask only color bits and look for green *pixel = 0x00000000;//0x00303040; // replace green with dark gray transparent (to help filtering) else *pixel |= 0xFF000000; // ensure alpha is set for opaque pixels pixel++; } } else { unsigned short i; unsigned short * pixel = (unsigned short *)GetPixBaseAddr( hPixMap ); for (i = 0; i < textureWidth * textureHeight; i++) { if ((*pixel & 0x7FFF) == 0x03E0) // mask only color bits and look for green *pixel = 0x0000;//0x0363; // replace green with dark gray transparent (to help filtering) else *pixel |= 0x8000; // ensure alpha is set for opaque pixels pixel++; } } return pGWorld; }