svvitch
digital signage player
|
00001 #include "TextContent.h" 00002 00003 #include <Poco/FileStream.h> 00004 #include <Poco/LineEndingConverter.h> 00005 #include <Poco/NumberParser.h> 00006 #include <Poco/RegularExpression.h> 00007 #include <Poco/string.h> 00008 #include <Poco/UnicodeConverter.h> 00009 00010 #include <gdiplus.h> 00011 00012 #include "Utils.h" 00013 00014 using namespace Gdiplus; 00015 00016 00017 TextContent::TextContent(Renderer& renderer, int splitType, float x, float y, float w, float h): Content(renderer, splitType, x, y, w, h), 00018 _texture(NULL), _referencedText(NULL), _async(false) 00019 { 00020 initialize(); 00021 } 00022 00023 TextContent::‾TextContent() { 00024 initialize(); 00025 } 00026 00027 void TextContent::initialize() { 00028 Poco::ScopedLock<Poco::FastMutex> lock(_initializeLock); 00029 close(); 00030 _dx = 0; 00031 _dy = 0; 00032 } 00033 00034 bool TextContent::open(const MediaItemPtr media, const int offset) { 00035 initialize(); 00036 Poco::RegularExpression re("^(sjis|shift_jis|shiftjis|ms932)$", Poco::RegularExpression::RE_CASELESS + Poco::RegularExpression::RE_EXTENDED); 00037 00038 bool valid = false; 00039 if (offset != -1 && offset < media->fileCount()) { 00040 MediaItemFile mif = media->files().at(offset); 00041 if (mif.type() == MediaTypeText) { 00042 _textFont = mif.getProperty("font"); 00043 if (_textFont.empty()) _textFont = config().textFont; 00044 _textHeight = mif.getNumProperty("fh", config().textHeight); 00045 _desent = 0; 00046 _c1 = mif.getHexProperty("c1", 0xffffffff); 00047 _c2 = mif.getHexProperty("c2", 0xffcccccc); 00048 _b1 = mif.getHexProperty("b1", 0xff000000); 00049 _b2 = mif.getHexProperty("b2", 0x00cccccc); 00050 _borderSize1 = mif.getFloatProperty("bs1", 4); 00051 _borderSize2 = mif.getFloatProperty("bs2", 0); 00052 _textStyle = mif.getProperty("style", config().textStyle); 00053 00054 _x = mif.getNumProperty("x", 0); 00055 _y = mif.getNumProperty("y", 0); 00056 _w = mif.getNumProperty("w", config().stageRect.right); 00057 _h = mif.getNumProperty("h", config().stageRect.bottom); 00058 _cx = mif.getNumProperty("cx", _x); 00059 _cy = mif.getNumProperty("cy", _y); 00060 _cw = mif.getNumProperty("cw", _w); 00061 _ch = mif.getNumProperty("ch", _h); 00062 _move = mif.getProperty("move"); 00063 _frameWait = mif.getNumProperty("fw", 0); 00064 _async = mif.getProperty("async") == "true"; 00065 //_dx = mif.getFloatProperty("dx", F(0)); 00066 //_dy = mif.getFloatProperty("dy", F(0)); 00067 _align = mif.getProperty("align"); 00068 _fitBounds = mif.getProperty("fit") == "true"; 00069 string pos = Poco::format("(%0.1hf,%0.1hf) %0.1hfx%0.1hf dx:%0.1hf dy:%0.1hf", _x, _y, _w, _h, _dx, _dy); 00070 pos += Poco::format(" fw:%d", _frameWait); 00071 _log.information(Poco::format("text: [%s] %s", _textFont, pos)); 00072 00073 if (!mif.file().empty() && mif.file().find("$") == string::npos) { 00074 string text; 00075 try { 00076 Poco::RegularExpression::Match m; 00077 bool isSJIS = re.match(mif.getProperty("encoding"), m); 00078 Poco::FileInputStream fis(Path(mif.file()).absolute(config().dataRoot).toString(), std::ios::in); 00079 try { 00080 Poco::InputLineEndingConverter ilec(fis); 00081 char line[1024]; 00082 int linenum = 1; 00083 while (!ilec.eof()) { 00084 line[0] = '¥0'; 00085 ilec.getline(line, sizeof(line)); 00086 if (!text.empty()) text += " "; 00087 if (isSJIS) { 00088 // sjis 00089 wstring wline; 00090 svvitch::sjis_utf16(string(line), wline); 00091 string utf8; 00092 Poco::UnicodeConverter::toUTF8(wline, utf8); 00093 text = Poco::cat(text, utf8); 00094 } else { 00095 // UTF-8 00096 text = Poco::cat(text, string(line)); 00097 } 00098 linenum++; 00099 } 00100 _log.information(Poco::format("lines: %d %s", linenum, text)); 00101 00102 drawTexture(text); 00103 valid = true; 00104 } catch (Poco::Exception& ex) { 00105 _log.warning(Poco::format("I/O error: %s", ex.displayText())); 00106 } 00107 fis.close(); 00108 } catch (Poco::PathNotFoundException& ex) { 00109 _log.warning(Poco::format("file not found: %s", mif.file())); 00110 } catch (Poco::Exception& ex) { 00111 _log.warning(Poco::format("failed read text: %s", ex.displayText())); 00112 } 00113 } else { 00114 // ファイル指定無し 00115 _log.information("text template mode"); 00116 valid = true; 00117 } 00118 } else { 00119 _log.warning("failed type error"); 00120 } 00121 } 00122 00123 if (valid) { 00124 _mediaID = media->id(); 00125 set("alpha", 1.0f); 00126 return true; 00127 } 00128 return false; 00129 } 00130 00131 void TextContent::setReference(TextContent* text) { 00132 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00133 _referencedText = text; 00134 _log.information("set reference text content"); 00135 } 00136 00137 void TextContent::play() { 00138 if (_move.find("roll-left-") == 0) { 00139 _x = _cx + _cw; 00140 _sx = _x; 00141 //_y = 0; 00142 int dx = 0; 00143 Poco::NumberParser::tryParse(_move.substr(10), dx); 00144 _dx = -dx; 00145 _log.debug(Poco::format("move: scroll-left: %0.1hf", _dx)); 00146 } else if (_move.find("roll-up-") == 0) { 00147 _y = _cy + _ch; 00148 _sy = _y; 00149 int dy = 0; 00150 Poco::NumberParser::tryParse(_move.substr(8), dy); 00151 _dy = -dy; 00152 _log.debug(Poco::format("move: scroll-up: %0.1hf", _dy)); 00153 } 00154 _playing = true; 00155 } 00156 00157 void TextContent::stop() { 00158 _playing = false; 00159 } 00160 00161 const bool TextContent::finished() { 00162 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00163 if (_move.empty() || _async) { 00164 return true; 00165 } 00166 return !_playing; 00167 } 00168 00170 void TextContent::close() { 00171 _mediaID.clear(); 00172 LPDIRECT3DTEXTURE9 old = NULL; 00173 { 00174 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00175 if (_referencedText) { 00176 _referencedText = NULL; 00177 } else { 00178 old = _texture; 00179 } 00180 _texture = NULL; 00181 } 00182 SAFE_RELEASE(old); 00183 _iw = 0; 00184 _ih = 0; 00185 _tw = 0; 00186 _th = 0; 00187 } 00188 00190 void TextContent::process(const DWORD& frame) { 00191 if (_align == "center") { 00192 _ax = (_w - _iw) / 2; 00193 } else if (_align == "right") { 00194 _ax = _w - _iw; 00195 } else { 00196 _ax = 0; 00197 } 00198 00199 { 00200 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00201 if (_referencedText) { 00202 _texture = _referencedText->_texture; 00203 _ax = _referencedText->_ax; 00204 _iw = _referencedText->_iw; 00205 _ih = _referencedText->_ih; 00206 _tw = _referencedText->_tw; 00207 _th = _referencedText->_th; 00208 } 00209 } 00210 if (!_mediaID.empty() && _texture && _playing) { 00211 if (!_move.empty()) { 00212 if (_frameWait <= 0 || (frame % _frameWait) == 0) { 00213 _x += _dx; 00214 _y += _dy; 00215 } 00216 if (!_async) { 00217 if (_move.find("roll-left-") == 0) { 00218 if (_dx != 0) { 00219 _duration = abs((_sx + _iw) / _dx); 00220 int current = abs((_sx - _x) / _dx); 00221 int dt = abs((_x - (_cx - _iw)) / _dx); 00222 const int fps = 60; 00223 unsigned long cu = current / fps; 00224 unsigned long re = dt / fps; 00225 string t1 = Poco::format("%02lu:%02lu:%02lu.%02d", cu / 3600, cu / 60, cu % 60, (current % fps) / 2); 00226 string t2 = Poco::format("%02lu:%02lu:%02lu.%02d", re / 3600, re / 60, re % 60, (dt % fps) / 2); 00227 set("time", Poco::format("%s %s", t1, t2)); 00228 set("time_current", t1); 00229 set("time_remain", t2); 00230 } 00231 if (_x < (_cx - _iw)) { 00232 // _log.information(Poco::format("text move finished: %hf %d %d", _x, _cx, _iw)); 00233 _dx = 0; 00234 _move.clear(); 00235 //_playing = false; 00236 } 00237 } else if (_move.find("roll-up-") == 0) { 00238 if (_dy != 0) { 00239 _duration = abs((_sy + _ih) / _dy); 00240 int current = abs((_sy - _y) / _dy); 00241 int dt = abs((_y - (_cy - _ih)) / _dy); 00242 const int fps = 60; 00243 unsigned long cu = current / fps; 00244 unsigned long re = dt / fps; 00245 string t1 = Poco::format("%02lu:%02lu:%02lu.%02d", cu / 3600, cu / 60, cu % 60, (current % fps) / 2); 00246 string t2 = Poco::format("%02lu:%02lu:%02lu.%02d", re / 3600, re / 60, re % 60, (dt % fps) / 2); 00247 set("time", Poco::format("%s %s", t1, t2)); 00248 set("time_current", t1); 00249 set("time_remain", t2); 00250 } 00251 if (_y < (_cy - _ih)) { 00252 _dy = 0; 00253 _move.clear(); 00254 } 00255 } else { 00256 _duration = 0; 00257 } 00258 } else { 00259 if (_x < (_cx - _iw)) _x = _cx + _cw; 00260 _duration = 0; 00261 } 00262 } 00263 //_x+=_dx; 00264 //_y+=_dy; 00265 _current++; 00266 if (_duration < _current) _current = _duration; 00267 } 00268 } 00269 00271 void TextContent::draw(const DWORD& frame) { 00272 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00273 if (!_mediaID.empty() && _texture && _playing) { 00274 LPDIRECT3DDEVICE9 device = _renderer.get3DDevice(); 00275 float alpha = getF("alpha", 1.0f); 00276 DWORD col = ((DWORD)(0xff * alpha) << 24) | 0xffffff; 00277 int cw = config().splitSize.cx; 00278 int ch = config().splitSize.cy; 00279 00280 switch (_splitType) { 00281 case 1: 00282 { 00283 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 00284 RECT scissorRect; 00285 device->GetScissorRect(&scissorRect); 00286 float x = _x + _ax; 00287 float y = _y; 00288 int ix = 0, sx = 0, sy = 0, dx = (int)x / (cw * config().splitCycles) * cw, dxx = (int)fmod(x, cw), dy = ch * ((int)x / cw) % (config().splitCycles * ch); 00289 int cww = 0; 00290 int chh = (ch > _ih)?_ih:ch; 00291 int clipX = _cx; 00292 while (dx < config().mainRect.right) { 00293 RECT rect = {dx, dy, dx + cw, dy + chh}; 00294 int cx = dx * config().splitCycles + dy / ch * cw; // cx=実際の映像の横位置 00295 if (cx > config().stageRect.right) break; 00296 int cxx = _cx - cx; 00297 if (cxx > cw) { 00298 SetRect(&rect, 0, 0, 0, 0); 00299 } else if (cxx >= 0) { 00300 SetRect(&rect, dx + cxx, rect.top, rect.right, rect.bottom); 00301 } 00302 cxx = _cx + _cw - cx; 00303 if (cxx < 0) { 00304 SetRect(&rect, 0, 0, 0, 0); 00305 } else if (cxx <= cw) { 00306 SetRect(&rect, rect.left, rect.top, dx + cxx, rect.bottom); 00307 } 00308 device->SetScissorRect(&rect); 00309 // if ((sx + cw - dxx) >= _tw) { 00310 if ((sx + cw - dxx) >= _tw) { 00311 // ソースの横がはみ出る() 00312 cww = _tw - sx; 00313 _renderer.drawTexture(dx + dxx, y + dy, cww, chh, sx, sy, cww, chh, _texture, 0, col, col, col, col); 00314 // _renderer.drawFontTextureText(dx + dxx, y + dy, 10, 10, 0xffff0000, Poco::format("%d,%d %d %d %d %d", sx, sy, cw, dxx, _tw, cww)); 00315 sx = 0; 00316 sy += _ih; 00317 if (sy < _th) { 00318 // srcを折り返してdstの残りに描画 00319 if (_th - sy < ch) chh = _th - sy; 00320 _renderer.drawTexture(dx + dxx + cww, y + dy, cw - cww, chh, sx, sy, cw - cww, chh, _texture, 0, col, col, col, col); 00321 // _renderer.drawFontTextureText(dx + dxx + cww, y + dy, 12, 12, 0xff00ff00, Poco::format("t%d,%d", sx, sy)); 00322 sx += cw - cww; 00323 ix += cw; 00324 dxx = cww + cw - cww; 00325 // if (ix >= _iw) _log.information(Poco::format("image check1: %d,%d %d", dx, dy, dxx)); 00326 } else { 00327 // dstの途中でsrcが全て終了 00328 dxx = _iw - ix; 00329 ix = _iw; 00330 // if (ix >= _iw) _log.information(Poco::format("image check2: %d,%d %d", dx, dy, dxx)); 00331 } 00332 } else { 00333 00334 if (_iw - ix < (cw - dxx)) { 00335 cww = _iw - ix; 00336 } else { 00337 cww = cw - dxx; 00338 } 00339 if (sx + cww >= _tw) { 00340 cww = _tw - sx; 00341 } 00342 _renderer.drawTexture(dx + dxx, y + dy, cww, chh, sx, sy, cww, chh, _texture, 0, col, col, col, col); 00343 // _renderer.drawFontTextureText(dx + dxx, y + dy, 12, 12, 0xffffcc00, Poco::format("%d,%d", sx, sy)); 00344 sx += cww; 00345 ix += cww; 00346 // dxx = cww; 00347 } 00348 if (ix >= _iw) { 00349 break; 00350 // dxx = cw - cww; 00351 // sx = 0; 00352 // ix = 0; 00353 } 00354 dxx = 0; 00355 dy += ch; 00356 if (dy >= config().splitCycles * ch) { 00357 dx += cw; 00358 dy = 0; 00359 } 00360 } 00361 device->SetScissorRect(&scissorRect); 00362 } 00363 break; 00364 00365 case 2: 00366 { 00367 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); 00368 RECT scissorRect; 00369 device->GetScissorRect(&scissorRect); 00370 int cww = cw; 00371 int chh = ch; 00372 int sw = config().stageRect.right / cw; 00373 int sh = config().stageRect.bottom / ch; 00374 for (int sy = 0; sy < sh; sy++) { 00375 int ox = (sy % 2) * cw * 8 + (L(_y / ch) % 2) * cw * 8 + config().stageRect.left; 00376 int oy = (sy / 2) * ch * 4 + (L(_y / ch) / 2) * ch * 4 + config().stageRect.top; 00377 for (int sx = 0; sx < sw; sx++) { 00378 // if (_x >= sx * cw + cw || _x + _tw < sx * cw) continue; 00379 int dx = (sx / 4) * cw; 00380 int dy = ch * 3 - (sx % 4) * ch; 00381 RECT rect = {ox + dx, oy + dy, ox + dx + cw, oy + dy + ch}; 00382 device->SetScissorRect(&rect); 00383 int tx = sx * cw -_x; 00384 int ty = -_dy; //sy * ch -_y; 00385 int tcw = cww; 00386 int tch = chh; 00387 if (_tw - tx < cww) tcw = _tw - tx; 00388 // if (_th - ty < chh) tch = _th - ty; 00389 if (tcw > 0 && tch > 0) _renderer.drawTexture(ox + dx, oy + dy, tcw, tch, tx, ty, tcw, tch, _texture, 0, col, col, col, col); 00390 } 00391 } 00392 device->SetScissorRect(&scissorRect); 00393 // _renderer.drawFontTextureText(0, conf->subRect.bottom - 40, 12, 16, 0xffcccccc, Poco::format("text: %d,%d", tx, ty)); 00394 } 00395 break; 00396 default: 00397 { 00398 float alpha = getF("alpha"); 00399 DWORD col = ((DWORD)(0xff * alpha) << 24) | 0xffffff; 00400 if (_fitBounds) { 00401 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 00402 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 00403 _renderer.drawTexture(_x, _y, _w, _ih, _texture, 0, col, col, col, col); 00404 device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); 00405 device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); 00406 } else { 00407 if (_ih != _th) { 00408 const int c = _th / _ih; 00409 for (int i = 0; i < c; i++) { 00410 _renderer.drawTexture(_x + _ax + i * _tw, _y, _tw, _ih, 0, i * _ih, _tw, _ih, _texture, 0, col, col, col, col); 00411 } 00412 } else { 00413 _renderer.drawTexture((int)_x + _ax, (int)_y, _texture, 0, col, col, col, col); 00414 } 00415 } 00416 } 00417 } 00418 } else { 00419 if (get("prepare") == "true") { 00420 int sy = getF("itemNo") * 20; 00421 DWORD col = 0xccffffff; 00422 _renderer.drawTexture(700, 600 + sy, 324, 20, _texture, 0, col, col, col, col); 00423 } 00424 } 00425 } 00426 00427 int TextContent::getTextWidth() { 00428 return _iw; 00429 } 00430 00431 int TextContent::getTextHeight() { 00432 return _ih; 00433 } 00434 00435 void TextContent::setFitBounds(bool fit) { 00436 _fitBounds = fit; 00437 } 00438 00439 void TextContent::setColor(DWORD c1, DWORD c2) { 00440 _c1 = c1; 00441 _c2 = c2; 00442 } 00443 00444 void TextContent::setBorder1(int size, DWORD col) { 00445 _borderSize1 = size; 00446 _b1 = col; 00447 } 00448 00449 void TextContent::setBorder2(int size, DWORD col) { 00450 _borderSize2 = size; 00451 _b2 = col; 00452 } 00453 00454 void TextContent::setFont(string font) { 00455 _textFont = font; 00456 } 00457 00458 void TextContent::setFontHeight(int height, int desent) { 00459 _textHeight = height; 00460 _desent = desent; 00461 } 00462 00463 void TextContent::setTextStyle(string style) { 00464 _textStyle = style; 00465 } 00466 00467 void TextContent::setAlign(string align) { 00468 _align = align; 00469 00470 if (_align == "center") { 00471 _ax = (_w - _iw) / 2; 00472 } else if (_align == "right") { 00473 _ax = _w - _iw; 00474 } else { 00475 _ax = 0; 00476 } 00477 _log.information(Poco::format("align change: %dx%d %dx%d align: %d", _iw, _ih, _tw, _th, _ax)); 00478 } 00479 00480 void TextContent::drawTexture(string text) { 00481 _text = text; 00482 Rect rect(0, 0, 0, 0); 00483 { 00484 Bitmap bitmap(1, 1, PixelFormat32bppARGB); 00485 drawText(text, bitmap, rect); 00486 } 00487 { 00488 int x = rect.X; 00489 int y = rect.Y; 00490 int w = rect.Width; 00491 int h = rect.Height; 00492 rect.Width = w - x; // rectの領域をx/y=0で作り直す 00493 rect.Height = h - y; // ただしx/yはクリアせずそのまま引き渡すことで、biasとして使用する 00494 _log.debug(Poco::format("bitmap: %d,%d %dx%d", x, y, w, h)); 00495 // int sh = config().stageRect.bottom; 00496 LPDIRECT3DTEXTURE9 texture = _renderer.createTexture(w, h, D3DFMT_A8R8G8B8); 00497 int tw = 0; 00498 int th = 0; 00499 int iw = 0; 00500 int ih = 0; 00501 if (texture) { 00502 D3DSURFACE_DESC desc; 00503 HRESULT hr = texture->GetLevelDesc(0, &desc); 00504 tw = desc.Width; 00505 th = desc.Height; 00506 _log.information(Poco::format("text texture: %dx%d", tw, th)); 00507 // th = sh; 00508 } else { 00509 // 指定サイズのテクスチャが作れない 00510 tw = config().imageSplitWidth; 00511 th = h; 00512 } 00513 if (w > tw || !texture) { 00514 // テクスチャの幅の方が小さい場合、テクスチャを折返しで作る 00515 SAFE_RELEASE(texture); 00516 Bitmap bitmap(w, h, PixelFormat32bppARGB); 00517 drawText(text, bitmap, rect); 00518 texture = _renderer.createTexture(tw, th * ((w + tw - 1) / tw), D3DFMT_A8R8G8B8); 00519 if (!texture) return; 00520 D3DSURFACE_DESC desc; 00521 HRESULT hr = texture->GetLevelDesc(0, &desc); 00522 _log.information(Poco::format("text texture(with turns %dx%d): %ux%u", tw, th, desc.Width, desc.Height)); 00523 _renderer.colorFill(texture, 0x00000000); 00524 D3DLOCKED_RECT lockRect; 00525 hr = texture->LockRect(0, &lockRect, NULL, 0); 00526 if (SUCCEEDED(hr)) { 00527 Bitmap dst(desc.Width, desc.Height, lockRect.Pitch, PixelFormat32bppARGB, (BYTE*)lockRect.pBits); 00528 Graphics g(&dst); 00529 int y = 0; 00530 for (int x = 0; x < w; x+=tw) { 00531 Rect rect(0, y, tw, th); 00532 g.SetClip(rect); 00533 g.DrawImage(&bitmap, -x, y); 00534 y += th; 00535 } 00536 g.Flush(); 00537 hr = texture->UnlockRect(0); 00538 // _w = 1024; 00539 iw = w; 00540 ih = h; 00541 tw = desc.Width; 00542 th = desc.Height; 00543 } 00544 00545 } else { 00546 // 折返し無し 00547 _renderer.colorFill(texture, 0x00000000); 00548 D3DLOCKED_RECT lockRect; 00549 HRESULT hr = texture->LockRect(0, &lockRect, NULL, 0); 00550 if (SUCCEEDED(hr)) { 00551 Bitmap bitmap(tw, th, lockRect.Pitch, PixelFormat32bppARGB, (BYTE*)lockRect.pBits); 00552 drawText(text, bitmap, rect); 00553 hr = texture->UnlockRect(0); 00554 _log.information(Poco::format("draw text texture: %dx%d", tw, th)); 00555 // _w = (float)rect.Width; 00556 iw = tw; 00557 ih = th; 00558 } 00559 } 00560 LPDIRECT3DTEXTURE9 old = NULL; 00561 { 00562 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00563 if (_texture) old = _texture; 00564 _texture = texture; 00565 // D3DXSaveTextureToFile(L"test_text.png", D3DXIFF_PNG, _texture, NULL); 00566 _iw = iw; 00567 _ih = ih; 00568 _tw = tw; 00569 _th = th; 00570 } 00571 SAFE_RELEASE(old); 00572 } 00573 00574 if (_align == "center") { 00575 _ax = (_w - _iw) / 2; 00576 } else if (_align == "right") { 00577 _ax = _w - _iw; 00578 } else { 00579 _ax = 0; 00580 } 00581 _log.information(Poco::format("texture updated: %dx%d %dx%d align: %d", _iw, _ih, _tw, _th, _ax)); 00582 } 00583 00584 void TextContent::drawText(string text, Bitmap& bitmap, Rect& rect) { 00585 int x = 0; 00586 int y = 0; 00587 int h = rect.GetBottom() - rect.GetTop(); 00588 if (rect.GetRight() - rect.GetLeft() != 0 || rect.GetBottom() - rect.GetTop() != 0) { 00589 x = -rect.X; 00590 y = -rect.Y; 00591 } 00592 00593 Graphics g(&bitmap); 00594 g.SetSmoothingMode(SmoothingModeHighQuality); 00595 g.SetTextRenderingHint(TextRenderingHintAntiAlias); 00596 00597 Gdiplus::FontFamily* ff = NULL; 00598 _renderer.getPrivateFontFamily(_textFont, &ff); 00599 if (!ff) { 00600 // アプリのフォントが利用できない場合システムから取得してみる 00601 std::wstring wfontFamily; 00602 Poco::UnicodeConverter::toUTF16(_textFont, wfontFamily); 00603 Font f(wfontFamily.c_str(), _textHeight); 00604 Gdiplus::FontFamily fontFamily; 00605 f.GetFamily(&fontFamily); 00606 ff = fontFamily.Clone(); 00607 WCHAR wname[64] = L""; 00608 ff->GetFamilyName(wname); 00609 string name; 00610 Poco::UnicodeConverter::toUTF8(wname, name); 00611 _log.information(Poco::format("installed font: %s", name)); 00612 } 00613 Gdiplus::FontStyle style; 00614 if (_textStyle == "bold") { 00615 style = Gdiplus::FontStyleBold; 00616 } else if (_textStyle == "italic") { 00617 style = Gdiplus::FontStyleItalic; 00618 } else if (_textStyle == "bolditalic") { 00619 style = Gdiplus::FontStyleBoldItalic; 00620 } else { 00621 style = Gdiplus::FontStyleRegular; 00622 } 00623 00624 Poco::RegularExpression re1("¥¥r|¥¥n"); 00625 re1.subst(text, " ", Poco::RegularExpression::RE_GLOBAL); 00626 std::wstring wtext; 00627 Poco::UnicodeConverter::toUTF16(text, wtext); 00628 size_t len = wcslen(wtext.c_str()); 00629 int bh = _borderSize1 + _borderSize2; 00630 GraphicsPath path; 00631 path.AddString(wtext.c_str(), len, ff, style, _textHeight, Point(x, y + bh), StringFormat::GenericDefault()); 00632 if (_borderSize2 > F(0)) { 00633 SolidBrush borderBrush2(_b2); 00634 Pen pen2(&borderBrush2, bh); 00635 pen2.SetLineJoin(LineJoinRound); 00636 g.DrawPath(&pen2, &path); 00637 } 00638 SolidBrush borderBrush1(_b1); 00639 Pen pen1(&borderBrush1, _borderSize1); 00640 if (_borderSize1 > F(0)) { 00641 pen1.SetLineJoin(LineJoinRound); 00642 g.DrawPath(&pen1, &path); 00643 } 00644 LinearGradientBrush foreBrush(Rect(0, 0, 1, rect.GetBottom() + rect.GetTop()), _c1, _c2, LinearGradientModeVertical); 00645 g.FillPath(&foreBrush, &path); 00646 00647 // pen1のサイズでrectを取得 00648 if (_borderSize1 > 0) path.Widen(&pen1); 00649 path.GetBounds(&rect); 00650 if (_borderSize2 > F(0)) { 00651 rect.Height = rect.Height + _borderSize2 * 2; 00652 } 00653 g.Flush(); 00654 SAFE_DELETE(ff); 00655 00656 if (false) { 00657 UINT num; // number of image encoders 00658 UINT size; // size, in bytes, of the image encoder array 00659 ImageCodecInfo* pImageCodecInfo; 00660 GetImageEncodersSize(&num, &size); 00661 pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); 00662 GetImageEncoders(num, size, pImageCodecInfo); 00663 for (int i = 0; i < num ; i ++) { 00664 if (!wcscmp(pImageCodecInfo[i].MimeType, L"image/png")) { 00665 bitmap.Save(L"test.png", &pImageCodecInfo[i].Clsid); 00666 break; 00667 } 00668 } 00669 free(pImageCodecInfo); 00670 } 00671 }