//SAMSUNG_THAI_EDITING_FIX >> FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const { SkPaint paint; SkPaint::FontMetrics metrics; float beforeWidth = 0.0f ; float afterWidth = 0.0f ; primaryFont()->platformData().setupPaint(&paint); size_t length = from ; if (length > 0) { beforeWidth = paint.measureText(run.characters(), length << 1); } length = to ; if (length > 0) { afterWidth = paint.measureText(run.characters(), length << 1); } return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), roundf(SkScalarToFloat(h))); }
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const { SkPaint paint; SkScalar width, left; SkPaint::FontMetrics metrics; primaryFont()->platformData().setupPaint(&paint); SkScalar spacing = paint.getFontMetrics(&metrics); float beforeWidth = SkScalarToFloat(paint.measureText(run.characters(), from << 1)); float afterWidth = SkScalarToFloat(paint.measureText(run.characters(), to << 1)); if (run.rtl()) { float totalWidth = SkScalarToFloat(paint.measureText(run.characters(), run.length() << 1)); return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), //roundf(SkScalarToFloat(spacing))); // Don't compute rect height, but use h. h); } else { return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), //roundf(SkScalarToFloat(spacing))); // Don't compute rect height, but use h. h); } }
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const { void* font = 0; float w = 0.f; const UChar* str = 0; UChar c = 0; const SimpleFontData* sfont = primaryFont(); float scale = 0; int i, len; if (!sfont) return 0.f; len = run.length(); if (!len) return 0.f; str = run.characters(); font = sfont->platformData().Font(); if (!font) return 0.f; scale = sfont->platformData().scale(); for (i=0; i<len; i++) { c = fixedChar(str[i]); if (!c) continue; w += (float)wkcFontGetCharWidthPeer(font, c) * scale; } return w; }
int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const { SkPaint paint; int count = run.length(); SkAutoSTMalloc<64, SkScalar> storage(count); SkScalar* widths = storage.get(); SkAutoSTMalloc<64, int> storageClusterIndex(count); int* clusterIndex = storageClusterIndex.get(); primaryFont()->platformData().setupPaint(&paint); //count = paint.getTextWidths(run.characters(), count << 1, widths); count = paint.getComplexTextWidths(run.characters(), count << 1, widths, clusterIndex); if (count > 0) { SkScalar pos = 0; for (int i = 0; i < count; i++) { if (x < SkScalarRound(pos + SkScalarHalf(widths[i]))) return clusterIndex[i]; pos += widths[i]; } } return run.length(); }
int Font::offsetForPositionForSimpleText(const TextRun& run, int position, bool includePartialGlyphs) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); QFontMetrics fm(font()); float delta = (float)position; int curPos = 0; do { float charWidth = fm.width(string[curPos]); delta -= charWidth; if (includePartialGlyphs) { if (delta + charWidth / 2 <= 0) break; } else { if (delta + charWidth <= 0) break; } } while (++curPos < string.size()); return curPos; #else Q_ASSERT(false); return 0; #endif }
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs); #endif // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. int x = static_cast<int>(xFloat); PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); int index, trailing; pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing); glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index); if (includePartialGlyphs) offset += trailing; g_free(utf8); g_object_unref(layout); return offset; }
TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) : m_font(font) , m_run(run) , m_startingX(startingX) , m_offsetX(m_startingX) , m_iterateBackwards(run.rtl()) { memset(&m_item, 0, sizeof(m_item)); // We cannot know, ahead of time, how many glyphs a given script run // will produce. We take a guess that script runs will not produce more // than twice as many glyphs as there are code points and fallback if // we find that we are wrong. m_maxGlyphs = run.length() * 2; createGlyphArrays(); m_item.log_clusters = new unsigned short[run.length()]; m_item.face = 0; m_item.font = allocHarfbuzzFont(); m_item.string = run.characters(); m_item.stringLength = run.length(); m_item.item.bidiLevel = run.rtl(); reset(); }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point, int from, int to) const { cairo_t* cr = context->platformContext(); cairo_save(cr); PangoLayout* layout = pango_cairo_create_layout(cr); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, run.length()); pango_layout_set_text(layout, utf8, -1); setPangoAttributes(this, run, layout, style.rtl()); // Set the text color to use for drawing. float red, green, blue, alpha; Color penColor = context->fillColor(); penColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); cairo_move_to(cr, point.x(), point.y()); PangoLayoutLine* layoutLine = pango_layout_get_line(layout, 0); pango_cairo_show_layout_line(cr, layoutLine); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { #if defined(USE_FREETYPE) if (!primaryFont()->platformData().m_pattern) { drawSimpleText(context, run, point, from, to); return; } #endif cairo_t* cr = context->platformContext(); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); // Get the region where this text will be laid out. We will use it to clip // the Cairo context, for when we are only painting part of the text run and // to calculate the size of the shadow buffer. PangoRegionType partialRegion = 0; char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); drawGlyphsShadow(context, cr, point, layoutLine, partialRegion); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); float red, green, blue, alpha; context->fillColor().getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); gdk_cairo_region(cr, partialRegion); cairo_clip(cr); pango_cairo_show_layout_line(cr, layoutLine); if (context->textDrawingMode() & TextModeStroke) { Color strokeColor = context->strokeColor(); strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); pango_cairo_layout_line_path(cr, layoutLine); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); destroyPangoRegion(partialRegion); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const TextStyle&, const FloatPoint& point) const { // FIXME: style, run.from()/length() cut-off ctx->platformContext()->drawText(point, QString::fromRawData( reinterpret_cast<const QChar*>( run.characters() + run.from()), run.length())); }
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const { String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString string = fromRawDataWithoutRef(sanitized); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); return line.xToCursor(position); }
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString wholeText = fromRawDataWithoutRef(sanitized); QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from)); int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping); int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping); return FloatRect(pt.x() + startX, pt.y(), width, h); }
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const { SkPaint paint; primaryFont()->platformData().setupPaint(&paint); //printf("--------- complext measure %d chars\n", run.to() - run.from()); SkScalar width = paint.measureText(run.characters(), run.length() << 1); return SkScalarToFloat(width); }
static QString qstring(const TextRun& run) { QString string((QChar *)run.characters(), run.length()); QChar *uc = string.data(); for (int i = 0; i < string.length(); ++i) { if (Font::treatAsSpace(uc[i].unicode())) uc[i] = 0x20; else if (Font::treatAsZeroWidthSpace(uc[i].unicode())) uc[i] = 0x200c; } return string; }
static float getWidth(PangoLayout *layout, const TextRun& run, int from, int to) { int layoutWidth; gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, to); pango_layout_set_text(layout, utf8, -1); g_free(utf8); pango_layout_get_size(layout, &layoutWidth, 0); float width = (float)layoutWidth / (double)PANGO_SCALE; return width; }
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString string = fromRawDataWithoutRef(sanitized); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); float x1 = line.cursorToX(from); float x2 = line.cursorToX(to); if (x2 < x1) qSwap(x1, x2); return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h); }
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString wholeText = fromRawDataWithoutRef(sanitized); QString selectedText = fromRawDataWithoutRef(sanitized, from, to - from); int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping); int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping); return FloatRect(pt.x() + startX, pt.y(), width, h); #else Q_ASSERT(false); return FloatRect(); #endif }
SVGTextMetrics::SVGTextMetrics(const Font& font, const TextRun& run, unsigned position, unsigned textLength) : m_width(0) , m_height(0) , m_length(0) { int extraCharsAvailable = textLength - (position + run.length()); int length = 0; m_width = font.floatWidth(run, extraCharsAvailable, length, m_glyph.name); m_height = font.fontMetrics().height(); m_glyph.unicodeString = String(run.characters(), length); m_glyph.isValid = true; ASSERT(length >= 0); m_length = static_cast<unsigned>(length); }
int Font::offsetForPositionForComplexText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const { PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout, style.rtl()); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); int index, trailing; pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing); glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index); g_object_unref(layout); g_free(utf8); return offset; }
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const { void* font = 0; const UChar* str = 0; const SimpleFontData* sfont = 0; int i, len; float x0,x1,x2; float scale = 0; UChar c = 0; len = run.length(); if (!len) return FloatRect(); if (from>=len || to>len) return FloatRect(); if (from>=to) return FloatRect(); if (from<0) from = 0; if (to>len) to = len; str = run.characters(); sfont = primaryFont(); if (!sfont) return FloatRect(); font = sfont->platformData().Font(); if (!font) return FloatRect(); scale = sfont->platformData().scale(); x0=x1=x2=0; for (i=0; i<from; i++) { c = fixedChar(str[i]); if (!c) continue; x0 += ((float)wkcFontGetCharWidthPeer(font, c) * scale); } for (i=from; i<to; i++) { c = fixedChar(str[i]); if (!c) continue; x1 += ((float)wkcFontGetCharWidthPeer(font, c) * scale); } for (i=to; i<len; i++) { c = fixedChar(str[i]); if (!c) continue; x2 += ((float)wkcFontGetCharWidthPeer(font, c) * scale); } if (run.rtl()) { return FloatRect(point.x() + x2, point.y(), x1, h); } else { return FloatRect(point.x() + x0, point.y(), x1, h); } }
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const { #if 0 SkPaint paint; primaryFont()->platformData().setupPaint(&paint); //printf("--------- complext measure %d chars\n", run.to() - run.from()); SkScalar width = paint.measureText(run.characters(), run.length() << 1); return SkScalarToFloat(width); #else WidthIterator it(this, run); it.advance(run.length()); return SkScalarToFloat(it.m_runWidthSoFar); #endif }
void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, FloatPoint const& point, int, int) const { SkCanvas* canvas = gc->platformContext()->mCanvas; SkPaint paint; if (!setupForText(&paint, gc, primaryFont())) { return; } // go to chars, instead of glyphs, which was set by setupForText() paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); canvas->drawText(run.characters(), run.length() << 1, SkFloatToScalar(point.x()), SkFloatToScalar(point.y()), paint); }
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int, int) const { SkPaint paint; SkScalar width, left; SkPaint::FontMetrics metrics; primaryFont()->platformData().setupPaint(&paint); width = paint.measureText(run.characters(), run.length() << 1); SkScalar spacing = paint.getFontMetrics(&metrics); return FloatRect(point.x(), point.y() - floorf(SkScalarToFloat(-metrics.fAscent)), roundf(SkScalarToFloat(width)), roundf(SkScalarToFloat(spacing))); }
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const { if (!run.length()) return 0; if (run.length() == 1 && treatAsSpace(run[0])) return QFontMetrics(font()).width(space) + run.padding(); String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); int w = QFontMetrics(font()).width(string); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; return w + run.padding(); }
float Font::floatWidthForComplexText(const TextRun& run) const { if (run.length() == 0) return 0.0f; PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); int width; pango_layout_get_pixel_size(layout, &width, 0); g_free(utf8); g_object_unref(layout); return width; }
float Font::floatWidthForComplexText(const TextRun& run, const TextStyle& style) const { if (run.length() == 0) return 0.0f; PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout, style.rtl()); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); g_free(utf8); int layoutWidth; pango_layout_get_size(layout, &layoutWidth, 0); float width = (float)layoutWidth / (double)PANGO_SCALE; g_object_unref(layout); return width; }
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { if (!primaryFont()->platformData().size()) return 0; if (!run.length()) return 0; String sanitized = Font::normalizeSpaces(run.characters(), run.length()); QString string = fromRawDataWithoutRef(sanitized); int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; return w + run.expansion(); }
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) return selectionRectForSimpleText(run, point, h, from, to); #endif PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); if (run.ltr()) { from = start - utf8; to = end - utf8; } else { from = end - utf8; to = start - utf8; } PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); int xPos; xPos = 0; if (from < layoutLine->length) pango_layout_line_index_to_x(layoutLine, from, FALSE, &xPos); float beforeWidth = PANGO_PIXELS_FLOOR(xPos); xPos = 0; if (run.ltr() || to < layoutLine->length) pango_layout_line_index_to_x(layoutLine, to, FALSE, &xPos); float afterWidth = PANGO_PIXELS(xPos); g_free(utf8); g_object_unref(layout); return FloatRect(point.x() + beforeWidth, point.y(), afterWidth - beforeWidth, h); }
SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run) { ASSERT(textRenderer); float scalingFactor = textRenderer->scalingFactor(); ASSERT(scalingFactor); const Font& scaledFont = textRenderer->scaledFont(); int length = 0; // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards. m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor; m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor; m_glyph.unicodeString = String(run.characters(), length); m_glyph.isValid = true; ASSERT(length >= 0); m_length = static_cast<unsigned>(length); }
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) if (!run.length()) return 0; String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; return w + run.padding(); #else Q_ASSERT(false); return 0.0f; #endif }