//---------------------------------------------------------------------- // 構造体比較関数 bool ScriptsAdd::equalStruct(tTJSVariant v1, tTJSVariant v2) { // タイプがオブジェクトなら特殊判定 if (v1.Type() == tvtObject && v2.Type() == tvtObject) { if (v1.AsObjectNoAddRef() == v2.AsObjectNoAddRef()) return true; tTJSVariantClosure &o1 = v1.AsObjectClosureNoAddRef(); tTJSVariantClosure &o2 = v2.AsObjectClosureNoAddRef(); // 関数どうしなら特別扱いで関数比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Function", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Function", NULL)== TJS_S_TRUE) return v1.DiscernCompare(v2); // Arrayどうしなら全項目を比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Array", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Array", NULL)== TJS_S_TRUE) { // 長さが一致していなければ比較失敗 tTJSVariant o1Count, o2Count; (void)o1.PropGet(0, L"count", &countHint, &o1Count, NULL); (void)o2.PropGet(0, L"count", &countHint, &o2Count, NULL); if (! o1Count.DiscernCompare(o2Count)) return false; // 全項目を順番に比較 tjs_int count = o1Count; tTJSVariant o1Val, o2Val; for (tjs_int i = 0; i < count; i++) { (void)o1.PropGetByNum(TJS_IGNOREPROP, i, &o1Val, NULL); (void)o2.PropGetByNum(TJS_IGNOREPROP, i, &o2Val, NULL); if (! equalStruct(o1Val, o2Val)) return false; } return true; } // Dictionaryどうしなら全項目を比較 if (o1.IsInstanceOf(0, NULL, NULL, L"Dictionary", NULL)== TJS_S_TRUE && o2.IsInstanceOf(0, NULL, NULL, L"Dictionary", NULL)== TJS_S_TRUE) { // 項目数が一致していなければ比較失敗 tjs_int o1Count, o2Count; (void)o1.GetCount(&o1Count, NULL, NULL, NULL); (void)o2.GetCount(&o2Count, NULL, NULL, NULL); if (o1Count != o2Count) return false; // 全項目を順番に比較 DictMemberCompareCaller *caller = new DictMemberCompareCaller(o2); tTJSVariantClosure closure(caller); tTJSVariant(o1.EnumMembers(TJS_IGNOREPROP, &closure, NULL)); bool result = caller->match; caller->Release(); return result; } } return v1.DiscernCompare(v2); }
/** * 合成結果の取得。取得領域は画像全体サイズ内におさまってる必要があります * 注意:PSDファイル自体に合成済み画像が存在しない場合は取得に失敗します * * @param layer 格納先レイヤ(width,heightサイズに調整される) * @return 取得に成功したら true */ bool PSD::getBlend(tTJSVariant layer) { if (!layer.AsObjectNoAddRef()->IsInstanceOf(0, 0, 0, L"Layer", NULL)) { TVPThrowExceptionMessage(L"not layer"); } // 合成結果を生成 if (imageData) { // 格納先を調整 ncbPropAccessor obj(layer); obj.SetValue(L"width", get_width()); obj.SetValue(L"height", get_height()); obj.SetValue(L"imageLeft", 0); obj.SetValue(L"imageTop", 0); obj.SetValue(L"imageWidth", get_width()); obj.SetValue(L"imageHeight", get_height()); // 画像データのコピー unsigned char *buffer = (unsigned char*)obj.GetValue(L"mainImageBufferForWrite", ncbTypedefs::Tag<tjs_int>()); int pitch = obj.GetValue(L"mainImageBufferPitch", ncbTypedefs::Tag<tjs_int>()); getMergedImage(buffer, psd::BGRA_LE, pitch); return true; } return false; }
/** * コンストラクタ */ TJSObject::TJSObject(HSQUIRRELVM v, int idx, tTJSVariant &instance) : instance(instance) { initSelf(v, idx); iTJSDispatch2 *objthis = instance.AsObjectNoAddRef(); // TJSインスタンスにネイティブインスタンスとして登録しておく iTJSNativeInstance *ninstance = this; objthis->NativeInstanceSupport(TJS_NIS_REGISTER, classId, &ninstance); // callSQ メソッド登録 tCallSQFunction *callSQ = new tCallSQFunction(); if (callSQ) { tTJSVariant val(callSQ, objthis); objthis->PropSet(TJS_MEMBERENSURE, TJS_W("callSQ"), NULL, &val, objthis); callSQ->Release(); } // missing メソッド登録 tMissingFunction *missing = new tMissingFunction(); if (missing) { tTJSVariant val(missing, objthis); const tjs_char *missingName = TJS_W("missing"); objthis->PropSet(TJS_MEMBERENSURE, missingName, NULL, &val, objthis); missing->Release(); // missing 有効化 tTJSVariant name(missingName); objthis->ClassInstanceInfo(TJS_CII_SET_MISSING, 0, &name); } }
/** * コンストラクタ */ TJSInstance::TJSInstance(Isolate *isolate, Local<Object> &obj, const tTJSVariant &variant) : isolate(isolate), TJSBase(variant) { HandleScope handle_scope(isolate); // Javascript オブジェクトに格納 wrap(isolate, obj); self.Reset(isolate, obj); self.SetWeak(this, release); iTJSDispatch2 *objthis = variant.AsObjectNoAddRef(); // TJSインスタンスにネイティブインスタンスとして登録しておく iTJSNativeInstance *ninstance = this; objthis->NativeInstanceSupport(TJS_NIS_REGISTER, classId, &ninstance); // callJS メソッド登録 tCallJSFunction *callJS = new tCallJSFunction(); if (callJS) { tTJSVariant val(callJS, objthis); objthis->PropSet(TJS_MEMBERENSURE, TJS_W("callJS"), NULL, &val, objthis); callJS->Release(); } // missing メソッド登録 tMissingFunction *missing = new tMissingFunction(); if (missing) { tTJSVariant val(missing, objthis); const tjs_char *missingName = TJS_W("missing"); objthis->PropSet(TJS_MEMBERENSURE, missingName, NULL, &val, objthis); missing->Release(); // missing 有効化 tTJSVariant name(missingName); objthis->ClassInstanceInfo(TJS_CII_SET_MISSING, 0, &name); } }
/** * 合成結果の取得。取得領域は画像全体サイズ内におさまってる必要があります * @param layer 格納先レイヤ(width,heightサイズに調整される) * @param left 合成結果取得領域の左上座標 * @param top 合成結果取得領域の左上座標 * @param width 取得サイズ横幅 * @param height 取得サイズ縦幅 * @return 取得に成功したら true */ bool getBlend(tTJSVariant layer, int left, int top, int width, int height) { if (!layer.AsObjectNoAddRef()->IsInstanceOf(0, 0, 0, L"Layer", NULL)) { TVPThrowExceptionMessage(L"not layer"); } // 合成結果を生成 if (psd_image_blend(context, left, top, width, height) == psd_status_done) { // 格納先を調整 ncbPropAccessor obj(layer); obj.SetValue(L"width", width); obj.SetValue(L"height", height); obj.SetValue(L"imageLeft", 0); obj.SetValue(L"imageTop", 0); obj.SetValue(L"imageWidth", width); obj.SetValue(L"imageHeight", height); // 合成結果画像データのコピー psd_argb_color *src = context->blending_image_data + top * context->width + left; int len = width * 4; unsigned char *buffer = (unsigned char*)obj.GetValue(L"mainImageBufferForWrite", ncbTypedefs::Tag<tjs_int>()); int pitch = obj.GetValue(L"mainImageBufferPitch", ncbTypedefs::Tag<tjs_int>()); for (int y=0;y<height;y++) { memcpy(buffer, (unsigned char*)src, len); src += context->width; buffer += pitch; } // 合成結果情報の破棄 psd_image_blend_free(context); return true; } return false; }
/** * 吉里吉里オブジェクトを squirrel に登録。squirrel 側で生成されたオブジェクトの場合は元のオブジェクト情報をそのまま返す * @return 登録成功 */ bool TJSObject::pushVariant(HSQUIRRELVM v, tTJSVariant &variant) { // 登録済みインスタンスかどうかの判定 iTJSNativeInstance *ninstance; if (TJS_SUCCEEDED(variant.AsObjectNoAddRef()->NativeInstanceSupport(TJS_NIS_GETINSTANCE, classId, &ninstance))) { // 元々 squirrel 側から登録されたオブジェクトの場合は元の squirrel オブジェクト情報をそのまま返す TJSObject *self = (TJSObject*)ninstance; self->self.push(v); return true; } return false; }
/** * 吉里吉里オブジェクトを javascriptオブジェクトに変換 * @return 登録成功 */ bool TJSInstance::getJSObject(Local<Object> &result, const tTJSVariant &variant) { iTJSDispatch2 *dispatch = variant.AsObjectNoAddRef(); iTJSNativeInstance *ninstance; if (TJS_SUCCEEDED(dispatch->NativeInstanceSupport(TJS_NIS_GETINSTANCE, classId, &ninstance))) { // Javascript側から登録されたオブジェクトの場合は元の Javascriptオブジェクト情報をそのまま返す TJSInstance *self = (TJSInstance*)ninstance; result = self->getObject(); return true; } return false; }
/** * Date クラスの時刻をファイル時刻に変換 * @param restore 参照先(Dateクラスインスタンス) * @param filetime ファイル時刻結果格納先 * @return 取得できたかどうか */ static bool restoreDate(tTJSVariant &restore, FILETIME &filetime) { if (restore.Type() != tvtObject) return false; iTJSDispatch2 *date = restore.AsObjectNoAddRef(); if (!date) return false; tTJSVariant result; if (dateGetTime->FuncCall(0, NULL, NULL, &result, 0, NULL, date) != TJS_S_OK) return false; tjs_uint64 ft = result.AsInteger(); ft *= 10000; ft += 0x19DB1DED53E8000; filetime.dwLowDateTime = (DWORD)( ft & 0xFFFFFFFF); filetime.dwHighDateTime = (DWORD)((ft >> 32) & 0xFFFFFFFF); return true; }
static void getVariantString(tTJSVariant &var, IWriter *writer) { switch(var.Type()) { case tvtVoid: writer->write(L"void"); break; case tvtObject: { iTJSDispatch2 *obj = var.AsObjectNoAddRef(); if (obj == NULL) { writer->write(L"null"); } else if (obj->IsInstanceOf(TJS_IGNOREPROP,NULL,NULL,L"Array",obj) == TJS_S_TRUE) { getArrayString(obj, writer); } else { getDictString(obj, writer); } } break; case tvtString: quoteString(var.GetString(), writer); break; case tvtOctet: quoteOctet(var.AsOctetNoAddRef(), writer); break; case tvtInteger: writer->write(L"int "); writer->write((tTVInteger)var); break; case tvtReal: writer->write(L"real "); writer->write((tTVReal)var); break; default: writer->write(L"void"); break; }; }
/** * レイヤデータの読み出し * @param layer 読み出し先レイヤ * @param no レイヤ番号 */ void getLayerData(tTJSVariant layer, int no) { if (!layer.AsObjectNoAddRef()->IsInstanceOf(0, 0, 0, L"Layer", NULL)) { TVPThrowExceptionMessage(L"not layer"); } checkLayerNo(no); psd_layer_record *lay = context->layer_records + no; if (lay->layer_type != psd_layer_type_normal) { TVPThrowExceptionMessage(L"invalid layer type"); } int width = lay->width; int height = lay->height; if (width <= 0 || height <= 0) { // サイズ0のレイヤはロードできない return; } ncbPropAccessor obj(layer); SETPROP(obj, lay, left); SETPROP(obj, lay, top); obj.SetValue(L"width", width); obj.SetValue(L"height", height); obj.SetValue(L"type", convBlendMode(lay->blend_mode)); SETPROP(obj, lay, opacity); SETPROP(obj, lay, visible); obj.SetValue(L"imageLeft", 0); obj.SetValue(L"imageTop", 0); obj.SetValue(L"imageWidth", width); obj.SetValue(L"imageHeight", height); obj.SetValue(L"name", layname(lay)); // 画像データのコピー psd_argb_color *src = lay->image_data; int srclen = width * 4; unsigned char *buffer = (unsigned char*)obj.GetValue(L"mainImageBufferForWrite", ncbTypedefs::Tag<tjs_int>()); int pitch = obj.GetValue(L"mainImageBufferPitch", ncbTypedefs::Tag<tjs_int>()); for (int y=0;y<height;y++) { memcpy(buffer, (unsigned char*)src, srclen); src += width; buffer += pitch; } }
/** * レイヤデータの読み出し(内部処理) * @param layer 読み出し先レイヤ * @param no レイヤ番号 * @param imageMode イメージモード */ void PSD::_getLayerData(tTJSVariant layer, int no, psd::ImageMode imageMode) { if (!layer.AsObjectNoAddRef()->IsInstanceOf(0, 0, 0, L"Layer", NULL)) { TVPThrowExceptionMessage(L"not layer"); } checkLayerNo(no); psd::LayerInfo &lay = layerList[no]; psd::LayerMask &mask = lay.extraData.layerMask; if (lay.layerType != psd::LAYER_TYPE_NORMAL && ! (lay.layerType == psd::LAYER_TYPE_FOLDER && imageMode == psd::IMAGE_MODE_MASK)) { TVPThrowExceptionMessage(L"invalid layer type"); } int left, top, width, height, opacity, type; bool dummyMask = false; if (imageMode == psd::IMAGE_MODE_MASK) { left = mask.left; top = mask.top; width = mask.width; height = mask.height; opacity = 255; type = ltPsNormal; if (width == 0 || height == 0) { left = top = 0; width = height = 1; dummyMask = true; } } else { left = lay.left; top = lay.top; width = lay.width; height = lay.height; opacity = lay.opacity; type = convBlendMode(lay.blendMode); } if (width <= 0 || height <= 0) { // サイズ0のレイヤはロードできない return; } ncbPropAccessor obj(layer); obj.SetValue(L"left", left); obj.SetValue(L"top", top); obj.SetValue(L"opacity", opacity); obj.SetValue(L"width", width); obj.SetValue(L"height", height); obj.SetValue(L"type", type); obj.SetValue(L"visible", lay.isVisible()); obj.SetValue(L"imageLeft", 0); obj.SetValue(L"imageTop", 0); obj.SetValue(L"imageWidth", width); obj.SetValue(L"imageHeight", height); obj.SetValue(L"name", layname(lay)); if (imageMode == psd::IMAGE_MODE_MASK) obj.SetValue(L"defaultMaskColor", mask.defaultColor); // 画像データのコピー unsigned char *buffer = (unsigned char*)obj.GetValue(L"mainImageBufferForWrite", ncbTypedefs::Tag<tjs_int>()); int pitch = obj.GetValue(L"mainImageBufferPitch", ncbTypedefs::Tag<tjs_int>()); if (dummyMask) { buffer[0] = buffer[1] = buffer[2] = mask.defaultColor; buffer[3] = 255; } else { getLayerImage(lay, buffer, psd::BGRA_LE, pitch, imageMode); } }
/** * tTJSVariant を VARIANT に格納する * @param result 格納先 * @param variant 格納元 */ void IDispatchWrapper::storeVariant(VARIANT &result, tTJSVariant &variant) { VariantClear(&result); switch (variant.Type()) { case tvtVoid: //log(L"void"); break; case tvtObject: // オブジェクト //log(L"object"); { switch (variant.Type()) { case tvtObject: V_VT(&result) = VT_DISPATCH; V_DISPATCH(&result) = new IDispatchWrapper(variant.AsObjectNoAddRef()); break; default: V_VT(&result) = VT_NULL; break; } } break; case tvtString: //log(L"string"); // 文字列 V_VT(&result) = VT_BSTR; V_BSTR(&result) = SysAllocString(variant.GetString()); break; case tvtOctet: //log(L"octet"); // オクテット列 { tTJSVariantOctet *octet = variant.AsOctetNoAddRef(); if (octet) { SAFEARRAY *psa; SAFEARRAYBOUND sabound; sabound.lLbound = 0; sabound.cElements = octet->GetLength(); if ((psa = SafeArrayCreate(VT_UI1, 1, &sabound))) { // データをコピーする unsigned char *p; if (SUCCEEDED(SafeArrayAccessData(psa, (LPVOID*)&p))) { memcpy(p, octet->GetData(), octet->GetLength()); SafeArrayUnaccessData(psa); V_VT(&result) = VT_ARRAY | VT_UI1; V_ARRAY(&result) = psa; } else { SafeArrayDestroy(psa); } } else { // メモリ不足例外 } } } break; case tvtInteger: // COM は 64bit をサポートしていない!! // ということで COM に渡す引数で整数値は 32bit を超えないように注意すること(涙) //log(L"integer"); V_VT(&result) = VT_I4; V_I4(&result) = (int)(variant); break; case tvtReal: //log(L"real"); V_VT(&result) = VT_R8; V_R8(&result) = (double)(variant); break; } }