Post by NeelCan we have simple API which does the same thing ?
A quick check of http://groups.google.com/ shows I answered this same
question in June of 2003. I've revised the code, because, in modern OS
X, PicHandles are no longer handles (You can't call SetHandleSize() on
them).
Here is the revised code:
// CText90View.h
#ifndef _H_CText90View
#define _H_CText90View
#pragma once
#include <LTextEditView.h>
class StScaledUpGWorld{
GWorldPtr mSaveGWorld;
GDHandle mSaveGD;
GWorldPtr mGW;
SInt32 mScaleFactor;
public:
StScaledUpGWorld(){ mGW = NULL; mScaleFactor = 4; }
StScaledUpGWorld(GraphicsImportComponent inGIC, long
scaleFactor = 1);
StScaledUpGWorld(PicHandle ph, long scaleFactor = 1);
~StScaledUpGWorld();
operator GWorldPtr () { return mGW; }
GWorldPtr Release();
void Rotate90();
void Adopt(GWorldPtr inGW, GWorldPtr saveGW, GDHandle saveGD);
void Draw(GWorldPtr gw = NULL, GDHandle gd = NULL);
private:
void Init(GraphicsImportComponent inGIC, long scaleFactor);
void Init(PicHandle ph, long scaleFactor);
void Die();
};
class StPicHandle{
PicHandle mPH;
public:
StPicHandle(PicHandle inPH);
~StPicHandle();
operator PicHandle(){ return mPH; }
PicHandle Release();
void Adopt(PicHandle inPH);
};
class CText90View : public LTextEditView {
public:
enum { class_ID = FOUR_CHAR_CODE('TxtV') };
CText90View( LStream* inStream );
virtual ~CText90View();
virtual void UserChangedText();
virtual void DrawSelf();
virtual void PrintPanelSelf(const PanelSpec& inPanel);
Boolean IsDirty() const
{
return mIsDirty;
}
void SetDirty(
Boolean inDirty)
{
mIsDirty = inDirty;
}
protected:
bool mIsDirty;
private:
CText90View();
CText90View(const CText90View& inOriginal);
CText90View& operator=(const CText90View& inRhs);
PicHandle GetAsPict(const Rect& r); // caller must KillPicture
StPicHandle mPh;
StScaledUpGWorld mGW;
};
void RotateAboutCenter(GraphicsImportComponent gic, SInt32 degrees);
void ScaleAboutTopLeft(GraphicsImportComponent gic, SInt32 scaleFactor);
PicHandle ScaleAboutTopLeft(PicHandle inPH, SInt32 scaleFactor);
PicHandle CopyPicture(PicHandle inPH);
#endif // _H_CText90View
// CText90View.cp -draws text rotated by 90 degrees.
// for printing, it renders to an offscreen GWorld
#include "CText90View.h"
#include <LStream.h>
#include <cstring>
#include <ImageCompression.h>
#include <QuicktimeComponents.h>
// make a GWorld initialized from a GraphicsImportComponent. Dispose
when goes out of scope.
StScaledUpGWorld::StScaledUpGWorld(GraphicsImportComponent inGIC, long
scaleFactor){
try{
Init(inGIC, scaleFactor);
}catch(...){
Die();
throw;
}
}
// make a GWorld initialized from a PicHandle. Dispose when goes out of
scope.
StScaledUpGWorld::StScaledUpGWorld(PicHandle ph, long scaleFactor){
try{
Init(ph, scaleFactor);
}catch(...){
Die();
throw;
}
}
void StScaledUpGWorld::Init(GraphicsImportComponent inGIC, long
scaleFactor){
GetGWorld(&mSaveGWorld, &mSaveGD);
mGW = NULL;
mScaleFactor = scaleFactor;
Rect r;
ThrowIfOSStatus_(GraphicsImportGetBoundsRect(inGIC, &r));
try{
StDisableDebugThrow_();
ThrowIfOSStatus_(NewGWorld(&mGW, 32, &r, NULL, NULL,
pixelsLocked));
}catch(...){
ThrowIfOSStatus_(NewGWorld(&mGW, 32, &r, NULL, NULL,
useTempMem|pixelsLocked));
}
LockPixels(GetGWorldPixMap(mGW));
GWorldPtr savePort;
GDHandle saveDev;
GetGWorld(&savePort, &saveDev);
SetGWorld(mGW, NULL);
EraseRect(&r);
SetGWorld(savePort, saveDev);
ThrowIfOSStatus_(GraphicsImportSetGWorld(inGIC, mGW, NULL));
ThrowIfOSStatus_(GraphicsImportDraw(inGIC));
SetGWorld(savePort, saveDev);
}
void StScaledUpGWorld::Init(PicHandle ph, long scaleFactor){
GetGWorld(&mSaveGWorld, &mSaveGD);
mGW = NULL;
mScaleFactor = scaleFactor;
Rect r;
r = (**ph).picFrame;
try{
StDisableDebugThrow_();
ThrowIfOSStatus_(NewGWorld(&mGW, 32, &r, NULL, NULL,
pixelsLocked));
}catch(...){
ThrowIfOSStatus_(NewGWorld(&mGW, 32, &r, NULL, NULL,
useTempMem|pixelsLocked));
}
LockPixels(GetGWorldPixMap(mGW));
GWorldPtr savePort;
GDHandle saveDev;
GetGWorld(&savePort, &saveDev);
SetGWorld(mGW, NULL);
EraseRect(&r);
StHandleLocker lock((Handle) ph);
DrawPicture(ph, &r);
SetGWorld(savePort, saveDev);
}
StScaledUpGWorld::~StScaledUpGWorld(){
Die();
}
void StScaledUpGWorld::Die(){
if(NULL != mGW){
SetGWorld(mSaveGWorld, mSaveGD);
DisposeGWorld(mGW);
}
}
void StScaledUpGWorld::Draw(GWorldPtr inDestGW, GDHandle gd){
if(NULL != mGW){
if(NULL == inDestGW){ inDestGW = mSaveGWorld; }
if(NULL == gd){ gd = mSaveGD; }
SetGWorld(inDestGW, gd);
Rect bounds;
Rect r;
GetPortBounds(mGW, &bounds);
r = bounds;
r.right = r.left + (r.right - r.left)/mScaleFactor;
r.bottom = r.top + (r.bottom - r.top)/mScaleFactor;
StColorState saveColors;
StColorState::Normalize();
CopyBits(GetPortBitMapForCopyBits(mGW),
GetPortBitMapForCopyBits(inDestGW),
&bounds, &r, ditherCopy, NULL);
}
}
void StScaledUpGWorld::Adopt(GWorldPtr inGW, GWorldPtr saveGW, GDHandle
saveGD){
if(inGW != mGW){
if(NULL != mGW){
DisposeGWorld(mGW);
}
mGW = inGW;
mSaveGWorld = saveGW;
mSaveGD = saveGD;
}
}
GWorldPtr StScaledUpGWorld::Release(){
GWorldPtr val = mGW;
mGW = NULL;
return val;
}
namespace {
/* ScanLineTranspose - p is a horizontal row of pixels. copy them, down,
into destPH at x coordinate x.
n is the number of pixels.
*/
void ScanLineTranspose(Ptr px, SInt32 n, PixMapHandle destPH, SInt32 x){
unsigned char *p, *pEnd, *dest;
SInt32 rowBytes;
p = reinterpret_cast<unsigned char*>(px);
dest = reinterpret_cast<unsigned char *>( GetPixBaseAddr(destPH));
rowBytes = GetPixRowBytes(destPH);
switch((**destPH).pixelSize){
case 32:
pEnd = p + n*4;
dest += x*4;
for(; p < pEnd;p += 4, dest += rowBytes){
* (SInt32*) dest = * (SInt32*) p;
}
break;
default:
Throw_(paramErr);
break;
}
}
}
/* Rotate90 - 90 degrees clockwise.
*/
void StScaledUpGWorld::Rotate90(){
PixMapHandle srcPH;
GWorldPtr destGW;
PixMapHandle destPH;
Rect r;
SInt32 x, y, xMax, yMax, rowBytes;
Ptr yp;
destGW = NULL;
srcPH = GetGWorldPixMap(mGW); // experiments show: when mem is tight,
can return NULL!
if(NULL == srcPH){
return;
}
if( ! LockPixels(srcPH)){
return;
}
r.left = (**srcPH).bounds.top;
r.top = (**srcPH).bounds.left;
r.right = (**srcPH).bounds.bottom;
r.bottom = (**srcPH).bounds.right;
if(noErr == NewGWorld(&destGW, (**srcPH).pixelSize, &r,
(**srcPH).pmTable, NULL, 0) ||
noErr == NewGWorld(&destGW,(**srcPH).pixelSize, &r,
(**srcPH).pmTable, NULL, useTempMem)){
destPH = GetGWorldPixMap(destGW); // experiments show: when mem
is tight, can return NULL!
if(NULL == destPH){
UnlockPixels(srcPH);
DisposeGWorld(destGW);
return;
}
if( ! LockPixels(destPH)){
UnlockPixels(srcPH);
DisposeGWorld(destGW);
return;
}
yp = GetPixBaseAddr(srcPH) ;
rowBytes = GetPixRowBytes(srcPH); // mask off flag bits.
xMax = ((**srcPH).bounds.right - (**srcPH).bounds.left);
yMax = ((**srcPH).bounds.bottom - (**srcPH).bounds.top);
for(x = yMax-1, y = 0; y < yMax; y++, x--, yp += rowBytes){
ScanLineTranspose(yp, xMax, destPH, x);
}
UnlockPixels(destPH);
}
UnlockPixels(srcPH);
Adopt(destGW, mSaveGWorld, mSaveGD);
}
// make a GraphicsImportComponent initialized from a picFileInMem.
Dispose when goes out of scope.
class StGraphicsImportComponent{
GraphicsImportComponent mGIC;
public:
explicit StGraphicsImportComponent(const FSSpec& inFS);
explicit StGraphicsImportComponent(Handle picFileInMem);
explicit StGraphicsImportComponent(GraphicsImportComponent
inGic){ mGIC = inGic;}
~StGraphicsImportComponent();
GraphicsImportComponent Release();
operator GraphicsImportComponent(){ return mGIC; }
private:
void Init(Handle picFileInMem);
void Die();
};
StGraphicsImportComponent::StGraphicsImportComponent(const FSSpec& inFS)
{
ThrowIfOSStatus_(GetGraphicsImporterForFile(&inFS, &mGIC));
}
StGraphicsImportComponent::StGraphicsImportComponent(Handle
picFileInMem){
try{
Init(picFileInMem);
}catch(...){
Die();
}
}
StGraphicsImportComponent::~StGraphicsImportComponent()
{
Die();
}
void StGraphicsImportComponent::Init(Handle picFileInMem){
mGIC = NULL;
ThrowIfOSStatus_(OpenADefaultComponent(GraphicsImporterComponentType,
kQTFileTypePicture, &mGIC));
ThrowIfOSStatus_(GraphicsImportSetDataHandle(mGIC, picFileInMem));
}
void StGraphicsImportComponent::Die(){
if(NULL != mGIC){
CloseComponent(mGIC);
}
}
GraphicsImportComponent StGraphicsImportComponent::Release(){
GraphicsImportComponent val = mGIC;
mGIC = NULL;
return val;
}
StPicHandle::StPicHandle(PicHandle inPH) : mPH(inPH){
}
StPicHandle::~StPicHandle(){
if(NULL != mPH){
KillPicture(mPH);
}
}
PicHandle StPicHandle::Release(){
PicHandle val = mPH;
mPH = NULL;
return val;
}
void StPicHandle::Adopt(PicHandle inPH){
if(inPH != mPH){
if(NULL != mPH){
KillPicture(mPH);
}
mPH = inPH;
}
}
class StPicFileFromHandle {
StHandleBlock mH;
public:
StPicFileFromHandle(PicHandle ph);
operator Handle(){ return mH; }
};
StPicFileFromHandle::StPicFileFromHandle(PicHandle ph) :
mH(512 + GetHandleSize(reinterpret_cast<Handle>(ph))){
std::memset(*mH, 0, 512);
BlockMoveData(*ph, *mH + 512,
GetHandleSize(reinterpret_cast<Handle>(ph)));
}
// CText90View - LStream constructor
CText90View::CText90View(LStream* inStream) : LTextEditView(inStream),
mPh(NULL){
mIsDirty = false;
}
// ~CText90View Destructor
CText90View::~CText90View(){
}
// UserChangedText
void CText90View::UserChangedText(){
if(not IsDirty()){
SetUpdateCommandStatus(true);
SetDirty(true);
}
}
void CText90View::PrintPanelSelf(const PanelSpec& /*inPanel*/){
GWorldPtr saveGW;
GDHandle saveGD;
GetGWorld(&saveGW, &saveGD);
mGW.Draw(GetMacPort(), saveGD);
}
void CText90View::DrawSelf(){
Rect r;
CalcLocalFrameRect(r);
StPicHandle ph(GetAsPict(r));
StPicFileFromHandle picFile(ph);
StGraphicsImportComponent gic(picFile);
RotateAboutCenter(gic, 90);
ThrowIfOSStatus_(GraphicsImportDraw(gic));
if(NULL == mGW){
GWorldPtr saveGW;
GDHandle saveGD;
Rect r;
CalcLocalFrameRect(r);
StPicHandle ph(GetAsPict(r));
StPicHandle ph2(ScaleAboutTopLeft(ph, 4));
StScaledUpGWorld gw(ph2, 4);
gw.Rotate90();
GetGWorld(&saveGW, &saveGD);
mGW.Adopt(gw.Release(), saveGW, saveGD);
}
}
void RotateAboutCenter(GraphicsImportComponent gic, SInt32 degrees){
Rect r;
MatrixRecord mat;
ThrowIfOSStatus_(GraphicsImportGetMatrix(gic, &mat));
ThrowIfOSStatus_(GraphicsImportGetBoundsRect(gic, &r));
RotateMatrix(&mat, degrees << 16,
static_cast<long>(r.right - r.left) << 15,
static_cast<long>(r.bottom - r.top) << 15);
GraphicsImportSetMatrix(gic, &mat);
}
void ScaleAboutTopLeft(GraphicsImportComponent gic, SInt32 scaleFactor){
Rect r;
MatrixRecord mat;
ThrowIfOSStatus_(GraphicsImportGetMatrix(gic, &mat));
ThrowIfOSStatus_(GraphicsImportGetBoundsRect(gic, &r));
ScaleMatrix(&mat, scaleFactor << 16, scaleFactor << 16,
static_cast<long>(r.left) << 16,
static_cast<long>(r.top) << 16);
GraphicsImportSetMatrix(gic, &mat);
}
// caller must dispose.
PicHandle ScaleAboutTopLeft(PicHandle inPH, SInt32 scaleFactor){
Rect r;
OpenCPicParams picParams;
r = (**inPH).picFrame;
r.right = r.left + (r.right - r.left)*scaleFactor;
r.bottom = r.top + (r.bottom - r.top)*scaleFactor;
picParams.srcRect = r;
picParams.hRes = 0x00480000 * 1;
picParams.vRes = picParams.hRes;
picParams.version = 2;
StPicHandle ph(OpenCPicture(&picParams));
ClipRect(&r);
StHandleLocker lock((Handle) inPH);
DrawPicture(inPH, &r);
ClosePicture();
return ph.Release();
}
namespace {
Handle CopyHandle(Handle inH){
ThrowIfOSErr_(HandToHand(&inH));
return inH;
}
}
PicHandle CopyPicture(PicHandle inPH){
return (PicHandle) CopyHandle((Handle) inPH);
}
PicHandle CText90View::GetAsPict(const Rect& r){
if(NULL != (PicHandle) mPh){
return CopyPicture(mPh);
}
OpenCPicParams picParams;
picParams.srcRect = r;
picParams.hRes = 0x00480000;
picParams.vRes = picParams.hRes;
picParams.version = 2;
// put it in a picture
StPicHandle ph(OpenCPicture(&picParams));
LTextEditView::DrawSelf();
ClosePicture();
mPh.Adopt(CopyPicture(ph));
return ph.Release();
}