📄 graphicsmodule.cpp
字号:
Py_INCREF(self);
return ret;
} else
return NULL;
} else {
SPyErr_SetFromSymbianOSErr(error);
return NULL;
}
}
static void _Image__bitmapapi_dealloc(void *gc, void *a2)
{
Py_DECREF((PyObject *)a2);
}
extern "C" PyObject*
Image__bitmapapi(Image_object *self, PyObject * /*args*/)
{
Py_INCREF(self);
return PyCObject_FromVoidPtrAndDesc(self->data->GetBitmap(), self,_Image__bitmapapi_dealloc);
}
/*
static void _graphics_rawscreen_dealloc(void *gc_)
{
CBitmapContext *gc=STATIC_CAST(CBitmapContext *,gc_);
CFbsScreenDevice *device=STATIC_CAST(CFbsScreenDevice *,gc->Device());
delete gc;
delete device;
}
extern "C" PyObject*
graphics_rawscreen(PyObject *args)
{
CFbsScreenDevice *dev;
dev=CFbsScreenDevice::NewL(TPtr(NULL,0),EColor64K);
//RHardwareBitmap hwbm=dev->HardwareBitmap();
//CBitmapDevice *dev=CCoeEnv::Static()->ScreenDevice();
CGraphicsContext *gc;
dev->CreateContext(gc);
gc->CancelClippingRect();
return PyCObject_FromVoidPtr(STATIC_CAST(CBitmapContext *,gc), _graphics_rawscreen_dealloc);
}
*/
/* LRU cache that maps Python level font specification objects to CFont objects. */
#ifdef EKA2
NONSHARABLE_CLASS(CPyFontCache) : public CBase {
#else
class CPyFontCache : public CBase {
#endif
public:
CPyFontCache(CBitmapDevice *aDevice):iDevice(aDevice) {}
~CPyFontCache();
int CFont_from_python_fontspec(PyObject *aArg, CFont *&aFont);
private:
/* This seems like a reasonable balance.
* It's probably rare for applications to constantly need more than 8 fonts. */
#define FONTCACHE_SIZE 8
struct TPyFontCacheEntry {
PyObject *pyfontspec;
CFont *cfont;
int last_access;
} iEntries[FONTCACHE_SIZE];
CBitmapDevice *iDevice;
int iTime;
};
CPyFontCache::~CPyFontCache(void)
{
for (int i=0; i<FONTCACHE_SIZE; i++) {
Py_XDECREF(iEntries[i].pyfontspec);
if (iEntries[i].cfont)
iDevice->ReleaseFont(iEntries[i].cfont);
}
}
int
CPyFontCache::CFont_from_python_fontspec(PyObject *aArg, CFont *&aFont)
{
int i;
for (i=0; i<FONTCACHE_SIZE; i++) {
if (iEntries[i].pyfontspec == aArg) {
iEntries[i].last_access = iTime;
aFont=iEntries[i].cfont;
return 0;
}
}
// No match found, find the oldest entry.
int oldestentry_time=0;
int oldestentry_index=0;
for (i=0; i<FONTCACHE_SIZE; i++)
/* Not doing oldestentry_time > iEntries[i].last_access since
* that wouldn't handle iTime wraparound correctly.
* At a hypothetical rate of 1000 font lookups a second
* we'd run into trouble already in 22 days :) */
if ((oldestentry_time - iEntries[i].last_access) >= 0) {
oldestentry_time=iEntries[i].last_access;
oldestentry_index=i;
}
// Lookup the font.
CFont *font;
int error = ::CFont_from_python_fontspec(aArg, font, *iDevice);
if (error != 0)
return error;
// If lookup was successful, release the old cache entry.
TPyFontCacheEntry &oldest=iEntries[oldestentry_index];
Py_XDECREF(oldest.pyfontspec);
if (oldest.cfont)
iDevice->ReleaseFont(oldest.cfont);
// Place font in cache.
iTime++;
oldest.pyfontspec = aArg;
Py_INCREF(aArg);
oldest.cfont = font;
oldest.last_access = iTime;
// All done.
aFont = font;
return 0;
}
// ******** Draw object
#define Draw_type ((PyTypeObject*)SPyGetGlobalString("DrawType"))
struct Draw_object {
PyObject_VAR_HEAD
PyObject *drawapi_cobject;
CBitmapContext *gc;
PyObject *font_spec_object;
CFont *cfont;
CPyFontCache *fontcache;
};
extern "C" PyObject *
graphics_Draw(PyObject* /*self*/, PyObject* args)
{
PyObject *drawable=NULL;
if (!PyArg_ParseTuple(args, "O", &drawable))
return NULL;
PyObject *drawapi_cobject=PyCAPI_GetCAPI(drawable,"_drawapi");
if (!drawapi_cobject) {
PyErr_SetString(PyExc_TypeError,
"Expected a drawable object as argument");
return NULL;
}
Draw_object *obj = PyObject_New(Draw_object, Draw_type);
if (obj == NULL)
return PyErr_NoMemory();
obj->gc=STATIC_CAST(CBitmapContext *,PyCObject_AsVoidPtr(drawapi_cobject));
obj->drawapi_cobject = drawapi_cobject;
obj->font_spec_object=NULL;
obj->cfont=NULL;
obj->fontcache=new CPyFontCache(static_cast<CBitmapDevice *>(obj->gc->Device()));
if (!obj->fontcache)
return PyErr_NoMemory();
return (PyObject *)obj;
}
extern "C" PyObject*
Draw_blit(Draw_object *self, PyObject *args, PyObject *keywds)
{
CBitmapContext *gc=self->gc;
PyObject *image_object=NULL;
PyObject *source_object=NULL;
PyObject *target_object=NULL;
int scaling=0;
PyObject *mask_object=NULL;
static const char *const kwlist[] =
{"image", "source", "target", "scale", "mask", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOiO", (char**)kwlist,
&image_object,
&source_object,
&target_object,
&scaling,
&mask_object)){
return NULL;
}
CFbsBitmap *source_bitmap=Bitmap_AsFbsBitmap(image_object);
if (!source_bitmap) {
PyErr_SetString(PyExc_TypeError, "Image object expected as 1st argument");
return NULL;
}
CFbsBitmap *mask_bitmap=NULL;
// If a mask is given, it must be a bitmap.
if (mask_object) {
mask_bitmap=Bitmap_AsFbsBitmap(mask_object);
if (!mask_bitmap) {
PyErr_SetString(PyExc_TypeError, "Mask must be an Image object");
return NULL;
}
#if S60_VERSION < 26
if (mask_bitmap->DisplayMode() != EGray2) {
PyErr_SetString(PyExc_ValueError, "Mask must be a binary (1-bit) Image. Partial transparency is not supported in S60 before 2nd edition FP2.");
return NULL;
}
#else
if (mask_bitmap->DisplayMode() != EGray2 && mask_bitmap->DisplayMode() != EGray256) {
PyErr_SetString(PyExc_ValueError, "Mask must be a binary (1-bit) or grayscale (8-bit) Image");
return NULL;
}
#endif
}
TSize target_size=gc->Device()->SizeInPixels();
TSize source_size=source_bitmap->SizeInPixels();
int fx1=0,fy1=0,fx2=source_size.iWidth,fy2=source_size.iHeight;
int tx1=0,ty1=0,tx2=target_size.iWidth,ty2=target_size.iHeight;
int n=0;
if (source_object) {
if (!PyCoordSeq_Length(source_object,&n) ||
!PyCoordSeq_GetItem(source_object,0,&fx1,&fy1) ||
((n==2) && !PyCoordSeq_GetItem(source_object,1,&fx2,&fy2))) {
PyErr_SetString(PyExc_TypeError, "invalid 'source' specification");
return NULL;
}
}
if (target_object) {
if (!PyCoordSeq_Length(target_object,&n) ||
!PyCoordSeq_GetItem(target_object,0,&tx1,&ty1) ||
((n==2) && !PyCoordSeq_GetItem(target_object,1,&tx2,&ty2))) {
PyErr_SetString(PyExc_TypeError, "invalid 'target' specification");
return NULL;
}
}
TRect fromRect(fx1,fy1,fx2,fy2);
TRect toRect(tx1,ty1,tx2,ty2);
if (scaling) {
if (mask_bitmap) {
PyErr_SetString(PyExc_ValueError,
"sorry, scaling and masking is not supported at the same time.");
return NULL;
}
gc->DrawBitmap(toRect,source_bitmap,fromRect);
} else {
if (mask_bitmap)
gc->BitBltMasked(TPoint(tx1,ty1),source_bitmap,fromRect,mask_bitmap,EFalse);
else
gc->BitBlt(TPoint(tx1,ty1),source_bitmap,fromRect);
}
PY_RETURN_NONE;
}
/* Note: All drawing functions are allowed to change pen and brush
color and pen size without restoring them. Other settings must be
restored to defaults on exit. */
static int
Graphics_ParseAndSetParams(Draw_object *self, PyObject *args, PyObject *keywds,
PyObject **coordseq_obj, int *n_coords,
float *start=NULL, float *end=NULL)
{
CBitmapContext *gc=self->gc;
PyObject
*outline_obj=NULL,
*fill_obj=NULL,
*pattern_obj=NULL;
int pen_width=1;
TRgb outline_color(0,0,0);
TRgb fill_color(0,0,0);
if (start && end) {
static const char *const kwlist[] = {"coords", "start", "end", "outline", "fill",
"width", "pattern", NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "Off|OOiO", (char**)kwlist,
coordseq_obj,
start,
end,
&outline_obj,
&fill_obj,
&pen_width,
&pattern_obj) ||
!PyCoordSeq_Length(*coordseq_obj, n_coords) ||
(outline_obj && outline_obj != Py_None && !ColorSpec_AsRgb(outline_obj,&outline_color)) ||
(fill_obj && fill_obj != Py_None && !ColorSpec_AsRgb(fill_obj,&fill_color)) ||
(pattern_obj && !Bitmap_Check(pattern_obj)))
return 0;
} else {
static const char *const kwlist[] = {"coords", "outline", "fill", "width", "pattern",
NULL};
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOiO", (char**)kwlist,
coordseq_obj,
&outline_obj,
&fill_obj,
&pen_width,
&pattern_obj) ||
!PyCoordSeq_Length(*coordseq_obj, n_coords) ||
(outline_obj && outline_obj != Py_None && !ColorSpec_AsRgb(outline_obj,&outline_color)) ||
(fill_obj && fill_obj != Py_None && !ColorSpec_AsRgb(fill_obj,&fill_color)) ||
(pattern_obj && !Bitmap_Check(pattern_obj)))
return 0;
}
if (outline_obj == Py_None)
outline_obj=NULL;
if (fill_obj == Py_None)
fill_obj=NULL;
gc->SetPenColor(outline_color);
gc->SetPenSize(TSize(pen_width,pen_width));
gc->SetPenStyle(outline_obj ? CGraphicsContext::ESolidPen : CGraphicsContext::ENullPen);
gc->SetBrushColor(fill_color);
if (pattern_obj) {
gc->UseBrushPattern(Bitmap_AsFbsBitmap(pattern_obj));
gc->SetBrushStyle(CGraphicsContext::EPatternedBrush);
} else {
gc->SetBrushStyle(fill_obj ? CGraphicsContext::ESolidBrush : CGraphicsContext::ENullBrush);
}
return 1;
}
static void
Graphics_ResetParams(Draw_object *self)
{
CBitmapContext *gc=self->gc;
gc->SetPenStyle(CGraphicsContext::ESolidPen);
gc->SetBrushStyle(CGraphicsContext::ENullBrush);
// Should we gc->DiscardBrushPattern() here?
}
extern "C" PyObject*
Draw_rectangle(Draw_object *self, PyObject *args, PyObject *keywds)
{
/*
{
CBitmapContext *gc=self->gc;
PyObject
*outline_obj=NULL,
*fill_obj=NULL,
*pattern_obj=NULL;
int i;
int pen_width=1;
TRgb outline_color(0,0,0);
TRgb fill_color(0,0,0);
static const char *const kwlist[] = {"coords", "outline", "fill", "width", "pattern",
NULL};
PyObject *coordseq_obj=NULL;
int n_coords=0;
PyArg_ParseTupleAndKeywords(args, keywds, "O|OOiO", (char**)kwlist,
&coordseq_obj,
&outline_obj,
&fill_obj,
&pen_width,
&pattern_obj);
}
*/
/*
CBitmapContext *gc=self->gc;
PyObject
*outline_obj=NULL,
*fill_obj=NULL,
*pattern_obj=NULL;
int i;
int pen_width=1;
TRgb outline_color(0,0,0);
TRgb fill_color(0,0,0);
static const char *const kwlist[] = {"coords", "outline", "fill", "width", "pattern",
NULL};
PyObject *coordseq_obj=NULL;
int n_coords=0;
if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|OOiO", (char**)kwlist,
&coordseq_obj,
&outline_obj,
&fill_obj,
&pen_width,
&pattern_obj) ||
!PyCoordSeq_Length(coordseq_obj, &n_coords) ||
(outline_obj && !ColorSpec_AsRgb(outline_obj,&outline_color)) ||
(fill_obj && !ColorSpec_AsRgb(fill_obj,&fill_color)) ||
(pattern_obj && !Bitmap_Check(pattern_obj))) {
return NULL;
}
gc->SetPenColor(outline_color);
gc->SetPenSize(TSize(pen_width,pen_width));
gc->SetPenStyle(outline_obj ? CGraphicsContext::ESolidPen : CGraphicsContext::ENullPen);
gc->SetBrushColor(fill_color);
gc->SetBrushStyle(fill_obj ? CGraphicsContext::ESolidBrush : CGraphicsContext::ENullBrush);
*/
//PY_RETURN_NONE;
//PY_RETURN_NONE;
CBitmapContext *gc=self->gc;
PyObject *coordseq_obj=NULL;
int n_coords,i;
if (!Graphics_ParseAndSetParams(self,args,keywds,&coordseq_obj,&n_coords))
return NULL;
/*PyObject *coordseq_obj=NULL;
int n_coords=2,i;
if (!PyArg_ParseTuple(args,"O", &coordseq_obj)) {
return NULL;
}
CBitmapContext *gc=self->gc;
gc->SetPenColor(TRgb(0,0,0));
gc->SetPenSize(TSize(1,1));
gc->SetPenStyle(CGraphicsContext::ENullPen);
gc->SetBrushColor(TRgb(255,0,0));
gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
*/
if (n_coords % 2 != 0) {
PyErr_SetString(PyExc_ValueError, "even number of coordinates expected");
goto error;
}
for (i=0; i<n_coords/2; i++) {
int x1,y1,x2,y2;
if (!PyCoordSeq_GetItem(coordseq_obj,i*2,&x1,&y1)||
!PyCoordSeq_GetItem(coordseq_obj,i*2+1,&x2,&y2))
goto error;
//sum += x1+y1+x2+y2;
gc->DrawRect(TRect(x1,y1,x2,y2));
}
// if (sum == 12332) // to defeat possible optimizer
// Py_INCREF(Py_None);
Graphics_ResetParams(self);
PY_RETURN_NONE;
error:
Graphics_ResetParams(self);
return NULL;
}
extern "C" PyObject*
Draw_ellipse(Draw_object *self, PyObject *args, PyObject *keywds)
{
CBitmapContext *gc=self->gc;
PyObject *coordseq_obj=NULL;
int n_coords,i;
if (!Graphics_ParseAndSetParams(self,args,keywds,&coordseq_obj,&n_coords))
return NULL;
if (n_coords % 2 != 0) {
PyErr_SetString(PyExc_ValueError, "even number of coordinates expected");
goto error;
}
for (i=0; i<n_coords/2; i++) {
int x1,y1,x2,y2;
if (!PyCoordSeq_GetItem(coordseq_obj,i*2,&x1,&y1)||
!PyCoordSeq_GetItem(coordseq_obj,i*2+1,&x2,&y2))
goto error;
gc->DrawEllipse(TRect(x1,y1,x2,y2));
}
Graphics_ResetParams(self);
PY_RETURN_NONE;
error:
Graphics_ResetParams(self);
return NULL;
}
static TPoint
TPoint_FromAngleAndBoundingBox(TRect bbox, float angle)
{
TInt cx=bbox.iTl.iX+((bbox.iBr.iX-bbox.iTl.iX)/2);
TInt cy=bbox.iTl.iY+((bbox.iBr.iY-bbox.iTl.iY)/2);
return TPoint((TInt)(cx+cos(angle)*1024), (TInt)(cy-sin(angle)*1024));
}
extern "C" PyObject*
Draw_arc(Draw_object *self, PyObject *args, PyObject *keywds)
{
CBitmapContext *gc=self->gc;
PyObject *coordseq_obj=NULL;
int n_coords,i;
float start_angle,end_angle;
if (!Graphics_ParseAndSetParams(self,args,keywds,&coordseq_obj,&n_coords,&start_angle,&end_angle))
return NULL;
if (n_coords % 2 != 0) {
PyErr_SetString(PyExc_ValueError, "even number of coordinates expected");
goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -