BytevectorCell* StringCell::toUtf8Bytevector(World &world, SliceIndexType start, SliceIndexType end) { CharRange range = charRange(start, end); if (range.isNull()) { return nullptr; } ByteLengthType newLength = range.endPointer - range.startPointer; SharedByteArray *byteArray; if ((newLength == byteLength()) && !dataIsInline()) { // Reuse our existing byte array byteArray = static_cast<HeapStringCell*>(this)->heapByteArray()->ref(); } else { // Create a new byte array and initialize it byteArray = SharedByteArray::createInstance(newLength); memcpy(byteArray->data(), range.startPointer, newLength); } return BytevectorCell::withByteArray(world, byteArray, newLength); }
StringCell* StringCell::copy(World &world, SliceIndexType start, SliceIndexType end) { // Allocating a string below can actually change "this" // That is super annoying StringCell *oldThis = const_cast<StringCell*>(this); alloc::StringRef thisRef(world, oldThis); CharRange range = charRange(start, end); if (range.isNull()) { // Invalid range return nullptr; } if ((range.charCount == charLength()) && !dataIsInline()) { // We're copying the whole string // Share our byte array void *cellPlacement = alloc::allocateCells(world); HeapStringCell *heapThis = static_cast<HeapStringCell*>(thisRef.data()); return new (cellPlacement) HeapStringCell( heapThis->heapByteArray()->ref(), heapThis->byteLength(), heapThis->charLength() ); } const ByteLengthType newByteLength = range.byteCount(); // Create the new string auto newString = StringCell::createUninitialized(world, newByteLength, range.charCount); if (thisRef->dataIsInline() && (oldThis != thisRef.data())) { // The allocator ran and moved us along with our inline data // We have to update our range ptrdiff_t byteDelta = reinterpret_cast<std::uint8_t*>(thisRef.data()) - reinterpret_cast<std::uint8_t*>(oldThis); range.relocate(byteDelta); } std::uint8_t *newUtf8Data = newString->utf8Data(); memcpy(newUtf8Data, range.startPointer, newByteLength); return newString; }
bool StringCell::fill(UnicodeChar unicodeChar, SliceIndexType start, SliceIndexType end) { assert(unicodeChar.isValid()); CharRange range = charRange(start, end); if (range.isNull()) { // Invalid range return false; } // Encode the new character utf8::EncodedChar encoded(utf8::encodeChar(unicodeChar)); return replaceBytes(range, encoded.data, encoded.size, range.charCount); }
// -------------------------------------------------------------- void GFontWin32GDIPlus::GetExtent( const char * str, int inCharCount, float * outWidth, float * outHeight, VGDevice * context ) const { if (!inCharCount) { *outWidth = *outHeight = 0; return; } // convert input string DWORD count = (DWORD)mbstowcs(NULL, str, inCharCount); WCHAR * wstr = (WCHAR*) malloc ((count + 1) * sizeof(WCHAR)); mbstowcs(wstr, str, inCharCount); //std::string s(str); //std::wstring wstr(s.length(),L' '); //std::copy(s.begin(), s.end(), wstr.begin()); Graphics* gdiContext = (Graphics*) GetContext( context ); /* -- known Gdi+ issue: We must use the following way to determine correct font extent because typical Graphics::MeasureString() method doesn't work properly (return values are incorrect due to antialiasing) */ Font* dgiFont = GetNativeFont(); // Layout rectangles used for drawing strings RectF layoutRect_A(0.0f, 0.0f, 1300.0f, 1300.0f); // 1 range of character positions within the string CharacterRange charRange(0, inCharCount); // String format used to apply to string when drawing StringFormat strFormat; // Set three ranges of character positions. strFormat.SetMeasurableCharacterRanges(1, &charRange); Region *pCharRangeRegions = new Region(); // Get the regions that correspond to the ranges within the string when // layout rectangle A is used. gdiContext->MeasureCharacterRanges( wstr, inCharCount, dgiFont, layoutRect_A, &strFormat, 1, pCharRangeRegions); RectF boundRect; pCharRangeRegions->GetBounds( &boundRect, gdiContext); *outWidth = boundRect.Width; *outHeight = boundRect.Height; free (wstr); }
double ASSISTANT::Text::GetTextWidth(const _TCHAR *textString, int textLength, LOGFONT *logFont) { if (textLength == 0) return 0; HDC hdc = ::CreateCompatibleDC(NULL); //Gdiplus::Graphics graphics(hdc); WCHAR *wcString = (WCHAR *)malloc((textLength+1)*sizeof(WCHAR)); #ifdef _UNICODE wcscpy(wcString, textString); #else MultiByteToWideChar(CP_ACP, 0, textString, textLength+1, wcString, textLength+1); #endif Gdiplus::RectF bbox; Gdiplus::Font font(hdc, logFont); Gdiplus::Graphics graphics(hdc); graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit); Gdiplus::StringFormat strFormat(Gdiplus::StringFormatFlagsMeasureTrailingSpaces); graphics.MeasureString(wcString, textLength, &font, Gdiplus::PointF(0.0, 0.0), &strFormat, &bbox); Gdiplus::CharacterRange charRange(0, textLength); strFormat.SetMeasurableCharacterRanges(1, &charRange); Gdiplus::Region pRangeRegion[1]; graphics.MeasureCharacterRanges(wcString, textLength, &font, bbox, &strFormat, 1, pRangeRegion); // get bounding rectangle Gdiplus::RectF rect; pRangeRegion[0].GetBounds(&rect, &graphics); if (wcString) delete wcString; ::DeleteObject(hdc); ::DeleteDC(hdc); return rect.Width; }
bool StringCell::replace(CharLengthType offset, const StringCell *from, SliceIndexType fromStart, SliceIndexType fromEnd) { CharRange fromRange = const_cast<StringCell*>(from)->charRange(fromStart, fromEnd); if (fromRange.isNull()) { return false; } CharRange toRange = charRange(offset, offset + fromRange.charCount); if (toRange.isNull() || (toRange.charCount != fromRange.charCount)) { return false; } return replaceBytes(toRange, fromRange.startPointer, fromRange.byteCount(), 1); }
// -------------------------------------------------------------- void GFontWin32GDIPlus::GetExtent( unsigned char c, float * outWidth, float * outHeight, VGDevice * context ) const { WCHAR wstr [] = L"0"; mbstowcs(wstr, (const char*)&c, 1); Graphics* gdiContext = (Graphics*) GetContext( context ); /* -- known Gdi+ issue: We must use the following way to determine correct font extent because typical Graphics::MeasureString() method doesn't work properly (return values are incorrect due to antialiasing) */ Font* dgiFont = GetNativeFont(); // Layout rectangles used for drawing strings RectF layoutRect_A(0.0f, 0.0f, 1300.0f, 1300.0f); // 1 range of character positions within the string CharacterRange charRange(0, 1); // String format used to apply to string when drawing StringFormat strFormat; // Set three ranges of character positions. strFormat.SetMeasurableCharacterRanges(1, &charRange); Region *pCharRangeRegions = new Region(); // Get the regions that correspond to the ranges within the string when // layout rectangle A is used. gdiContext->MeasureCharacterRanges( wstr, 1, dgiFont, layoutRect_A, &strFormat, 1, pCharRangeRegions); RectF boundRect; pCharRangeRegions->GetBounds( &boundRect, gdiContext); *outHeight = boundRect.Height; *outWidth = boundRect.Width; // in some cases (when some symbols must be forced into char map), extent needs to be fixed if (c == 139) *outWidth = 6.0; }
void ASSISTANT::Text::Draw(CDC *pDC, float _zoomFactor, double dOffX, double dOffY) { if (!visible) return; if (text.IsEmpty()) return; Gdiplus::Graphics graphics(pDC->m_hDC); graphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit); // Move and Scale graphics.TranslateTransform((Gdiplus::REAL)dOffX, (Gdiplus::REAL)dOffY); Gdiplus::Font gdipFont(pDC->m_hDC, &m_logFont); Gdiplus::FontFamily fontFamily; gdipFont.GetFamily(&fontFamily); int fontStyle = GetValidFontStyle(fontFamily); Gdiplus::REAL ascent = fontFamily.GetCellAscent(fontStyle) * (gdipFont.GetSize() / fontFamily.GetEmHeight(fontStyle)); Gdiplus::PointF drawPoint; drawPoint.X = (Gdiplus::REAL)m_dX; drawPoint.Y = (Gdiplus::REAL)(m_dY - ascent); // convert text string to WCHAR format int iStringLength = text.GetLength(); WCHAR *wcString = (WCHAR *)malloc((iStringLength+1)*sizeof(WCHAR)); // +1 for null termination #ifdef _UNICODE wcscpy(wcString, text); #else MultiByteToWideChar(CP_ACP, 0, text, iStringLength+1, wcString, iStringLength+1); #endif // compute real text width Gdiplus::StringFormat measureStringFormat(Gdiplus::StringFormatFlagsMeasureTrailingSpaces); Gdiplus::RectF bbox; graphics.MeasureString(wcString, iStringLength, &gdipFont, Gdiplus::PointF(0.0, 0.0), &measureStringFormat, &bbox); Gdiplus::CharacterRange charRange(0, iStringLength); measureStringFormat.SetMeasurableCharacterRanges(1, &charRange); Gdiplus::Region pRangeRegion[1]; graphics.MeasureCharacterRanges(wcString, iStringLength, &gdipFont, bbox, &measureStringFormat, 1, pRangeRegion); // get bounding rectangle Gdiplus::RectF rect; pRangeRegion[0].GetBounds(&rect, &graphics); Gdiplus::REAL realTextWidth = rect.Width; if (iStringLength > 1 && m_dWidth != 0 && realTextWidth != m_dWidth) { Gdiplus::REAL scaleX = (Gdiplus::REAL)(m_dWidth / realTextWidth); graphics.ScaleTransform(scaleX, 1.0); drawPoint.X = (Gdiplus::REAL)(m_dX / scaleX); //(x_*scaleX - x_); } // the text should begin at x, y drawPoint.X -= rect.X; graphics.ScaleTransform(_zoomFactor, _zoomFactor); Gdiplus::Color clrText(m_argbLineColor); Gdiplus::SolidBrush solidBrush(clrText); graphics.DrawString(wcString, iStringLength, &gdipFont, drawPoint, &measureStringFormat, &solidBrush); if (wcString) delete wcString; }