のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

drawBidiText >> width > floatWidthForComplexText > widthOfFullRun > nextScriptRun > setupFontForScriptRun

    148 void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
    149 {
    150     if (!pluginCrashedOrWasMissing())
    151         return;
    152 
    153     if (paintInfo.phase == PaintPhaseSelection)
    154         return;
    155 
    156     GraphicsContext* context = paintInfo.context;
    157     if (context->paintingDisabled())
    158         return;
    159 
    160     FloatRect contentRect;
    161     Path path;
    162     FloatRect replacementTextRect;
    163     Font font;
    164     TextRun run("");
    165     float textWidth;
    166     if (!getReplacementTextGeometry(tx, ty, contentRect, path, replacementTextRect, font, run, textWidth))
    167         return;
    168 
    169     context->save();
    170     context->clip(contentRect);
    171     context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedRoundedRectOpacity : replacementTextRoundedRectOpacity);
    172     context->setFillColor(m_missingPluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : Color::white, style()->colorSpace());
    173     context->fillPath(path);
    174 
    175     const FontMetrics& fontMetrics = font.fontMetrics();
    176     float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2);
    177     float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent());
    178     context->setAlpha(m_missingPluginIndicatorIsPressed ? replacementTextPressedTextOpacity : replacementTextTextOpacity);
    179     context->setFillColor(Color::black, style()->colorSpace());
    180     context->drawBidiText(font, run, FloatPoint(labelX, labelY)); <=======
    181     context->restore();
    182 }
    212 void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
    213 {
    214     if (style()->visibility() != VISIBLE)
    215         return;
    216     ASSERT(m_fileChooser);
    217 
    218     // Push a clip.
    219     if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
    220         IntRect clipRect(tx + borderLeft(), ty + borderTop(),
    221                          width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight);
    222         if (clipRect.isEmpty())
    223             return;
    224         paintInfo.context->save();
    225         paintInfo.context->clip(clipRect);
    226     }
    227 
    228     if (paintInfo.phase == PaintPhaseForeground) {
    229         const String& displayedFilename = fileTextValue();
    230         unsigned length = displayedFilename.length();
    231         const UChar* string = displayedFilename.characters();
    232         TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, !style()->isLeftToRightDirection(), style()->unicodeBidi() == Override);
    233 
    234         // Determine where the filename should be placed
    235         int contentLeft = tx + borderLeft() + paddingLeft();
    236         int buttonAndIconWidth = m_button->renderBox()->width() + afterButtonSpacing
    237             + (m_fileChooser->icon() ? iconWidth + iconFilenameSpacing : 0);
    238         int textX;
    239         if (style()->isLeftToRightDirection())
    240             textX = contentLeft + buttonAndIconWidth;
    241         else
    242             textX = contentLeft + contentWidth() - buttonAndIconWidth - style()->font().width(textRun);
    243         // We want to match the button's baseline
    244         RenderButton* buttonRenderer = toRenderButton(m_button->renderer());
    245         int textY = buttonRenderer->absoluteBoundingBoxRect().y()
    246             + buttonRenderer->marginTop() + buttonRenderer->borderTop() + buttonRenderer->paddingTop()
    247             + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
    248 
    249         paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace());
    250 
    251         // Draw the filename
    252         paintInfo.context->drawBidiText(style()->font(), textRun, IntPoint(textX, textY)); <==========
    253 
    254         if (m_fileChooser->icon()) {
    255             // Determine where the icon should be placed
    256             int iconY = ty + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
    257             int iconX;
    258             if (style()->isLeftToRightDirection())
    259                 iconX = contentLeft + m_button->renderBox()->width() + afterButtonSpacing;
    260             else
    261                 iconX = contentLeft + contentWidth() - m_button->renderBox()->width() - afterButtonSpacing - iconWidth;
    262 
    263             // Draw the file icon
    264             m_fileChooser->icon()->paint(paintInfo.context, IntRect(iconX, iconY, iconWidth, iconHeight));
    265         }
    266     }
    267 
    268     // Paint the children.
    269     RenderBlock::paintObject(paintInfo, tx, ty);
    270 
    271     // Pop the clip.
    272     if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds)
    273         paintInfo.context->restore();
    274 }
   358 void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
    359 {
    360     SelectElement* select = toSelectElement(static_cast<Element*>(node()));
    361     const Vector<Element*>& listItems = select->listItems();
    362     Element* element = listItems[listIndex];
    363     OptionElement* optionElement = toOptionElement(element);
    364 
    365     RenderStyle* itemStyle = element->renderStyle();
    366     if (!itemStyle)
    367         itemStyle = style();
    368 
    369     if (itemStyle->visibility() == HIDDEN)
    370         return;
    371 
    372     String itemText;
    373     if (optionElement)
    374         itemText = optionElement->textIndentedToRespectGroupLabel();
    375     else if (OptionGroupElement* optionGroupElement = toOptionGroupElement(element))
    376         itemText = optionGroupElement->groupLabelText();
    377 
    378     Color textColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyColor) : style()->visitedDependentColor(CSSPropertyColor);
    379     if (optionElement && optionElement->selected()) {
    380         if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
    381             textColor = theme()->activeListBoxSelectionForegroundColor();
    382         // Honor the foreground color for disabled items
    383         else if (!element->disabled())
    384             textColor = theme()->inactiveListBoxSelectionForegroundColor();
    385     }
    386 
    387     ColorSpace colorSpace = itemStyle->colorSpace();
    388     paintInfo.context->setFillColor(textColor, colorSpace);
    389 
    390     unsigned length = itemText.length();
    391     const UChar* string = itemText.characters();
    392     TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, !itemStyle->isLeftToRightDirection(), itemStyle->unicodeBidi() == Override);
    393     Font itemFont = style()->font();
    394     IntRect r = itemBoundingBoxRect(tx, ty, listIndex);
    395     r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r));
    396 
    397     if (isOptionGroupElement(element)) {
    398         FontDescription d = itemFont.fontDescription();
    399         d.setWeight(d.bolderWeight());
    400         itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
    401         itemFont.update(document()->styleSelector()->fontSelector());
    402     }
    403 
    404     // Draw the item text
    405     if (itemStyle->visibility() != HIDDEN)
    406         paintInfo.context->drawBidiText(itemFont, textRun, r.location());
    407 }
    630 void RenderTextControl::paintPlaceholder(PaintInfo& paintInfo, int tx, int ty)
    631 {
    632     if (style()->visibility() != VISIBLE)
    633         return;
    634 
    635     IntRect clipRect(tx + borderLeft(), ty + borderTop(), width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop());
    636     if (clipRect.isEmpty())
    637         return;
    638 
    639     paintInfo.context->save();
    640 
    641     paintInfo.context->clip(clipRect);
    642 
    643     RefPtr<RenderStyle> placeholderStyle = getCachedPseudoStyle(INPUT_PLACEHOLDER);
    644     if (!placeholderStyle)
    645         placeholderStyle = style();
    646 
    647     paintInfo.context->setFillColor(placeholderStyle->visitedDependentColor(CSSPropertyColor), placeholderStyle->colorSpace());
    648 
    649     String placeholderText = static_cast<HTMLTextFormControlElement*>(node())->strippedPlaceholder();
    650     TextRun textRun(placeholderText.characters(), placeholderText.length(), false, 0, 0, TextRun::AllowTrailingExpansion, !placeholderStyle->isLeftToRightDirection(), placeholderStyle->unicodeBidi() == Override);
    651 
    652     RenderBox* textRenderer = innerTextElement() ? innerTextElement()->renderBox() : 0;
    653     if (textRenderer) {
    654         IntPoint textPoint;
    655         textPoint.setY(ty + textBlockInsetTop() + placeholderStyle->fontMetrics().ascent());
    656         if (placeholderStyle->isLeftToRightDirection())
    657             textPoint.setX(tx + textBlockInsetLeft());
    658         else
    659             textPoint.setX(tx + width() - textBlockInsetRight() - style()->font().width(textRun));
    660 
    661         paintInfo.context->drawBidiText(placeholderStyle->font(), textRun, textPoint); <==========
    662     }
    663     paintInfo.context->restore();
    664 }

=========================================================================================
=========================================================================================

    395 void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point)
    396 {
    397     if (paintingDisabled())
    398         return;
    399 
    400     // FIXME: This ownership should be reversed. We should pass BidiRunList
    401     // to BidiResolver in createBidiRunsForLine.
    402     BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
    403     BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
    404 
    405     WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft;
    406 
    407     bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, BidiContext::create(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride())));
    408 
    409     bidiResolver.setPosition(TextRunIterator(&run, 0));
    410     bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length()));
    411 
    412     if (!bidiRuns.runCount())
    413         return;
    414 
    415     FloatPoint currPoint = point;
    416     BidiCharacterRun* bidiRun = bidiRuns.firstRun();
    417     while (bidiRun) {
    418 
    419         TextRun subrun = run;
    420         subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start());
    421         subrun.setRTL(bidiRun->level() % 2);
    422         subrun.setDirectionalOverride(bidiRun->dirOverride(false));
    423 
    424         font.drawText(this, subrun, currPoint);
    425 
    426         bidiRun = bidiRun->next();
    427         // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here.
    428         if (bidiRun)
    429             currPoint.move(font.width(subrun), 0); <=============
    430     }
    431 
    432     bidiRuns.deleteRuns();
    433 }
   168 float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
    169 {
    170 #if ENABLE(SVG_FONTS)
    171     if (primaryFont()->isSVGFont())
    172         return floatWidthUsingSVGFont(run);
    173 #endif
    174 
    175     CodePath codePathToUse = codePath(run);
    176     if (codePathToUse != Complex) {
    177         // If the complex text implementation cannot return fallback fonts, avoid
    178         // returning them for simple text as well.
    179         static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
    180         return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0);
    181     }
    182 
    183     return floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
    184 }
    186 float Font::width(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
    187 {
    188 #if !ENABLE(SVG_FONTS)
    189     UNUSED_PARAM(extraCharsAvailable);
    190 #else
    191     if (primaryFont()->isSVGFont())
    192         return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
    193 #endif
    194 
    195     charsConsumed = run.length();
    196     glyphName = "";
    197 
    198     if (codePath(run) != Complex)
    199         return floatWidthForSimpleText(run, 0);
    200 
    201     return floatWidthForComplexText(run);
    202 }
   1076 float Font::floatWidthForComplexText(const TextRun& run,
   1077             HashSet<const SimpleFontData*>*, GlyphOverflow*) const
   1078 {
   1079     TextRunWalker walker(run, 0, 0, this);
   1080     walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
   1081     return walker.widthOfFullRun();
   1082 }
 675 float TextRunWalker::widthOfFullRun()
    676 {
    677     float widthSum = 0;
    678     while (nextScriptRun())
    679         widthSum += width();
    680 
    681     return widthSum;
    682 }
    629 // Advance to the next script run, returning false when the end of the
    630 // TextRun has been reached.
    631 bool TextRunWalker::nextScriptRun()
    632 {
    633     if (m_iterateBackwards) {
    634         // In right-to-left mode we need to render the shaped glyph backwards and
    635         // also render the script runs themselves backwards. So given a TextRun:
    636         //    AAAAAAACTTTTTTT   (A = Arabic, C = Common, T = Thai)
    637         // we render:
    638         //    TTTTTTCAAAAAAA
    639         // (and the glyphs in each A, C and T section are backwards too)
    640         if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(),
    641             m_run.length(), &m_indexOfNextScriptRun))
    642             return false;
    643     } else {
    644         if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(),
    645             m_run.length(), &m_indexOfNextScriptRun))
    646             return false;
    647 
    648         // It is actually wrong to consider script runs at all in this code.
    649         // Other WebKit code (e.g. Mac) segments complex text just by finding
    650         // the longest span of text covered by a single font.
    651         // But we currently need to call hb_utf16_script_run_next anyway to fill
    652         // in the harfbuzz data structures to e.g. pick the correct script's shaper.
    653         // So we allow that to run first, then do a second pass over the range it
    654         // found and take the largest subregion that stays within a single font.
    655         const FontData* glyphData = m_font->glyphDataForCharacter(
    656            m_item.string[m_item.item.pos], false).fontData;
    657         unsigned endOfRun;
    658         for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
    659             const FontData* nextGlyphData = m_font->glyphDataForCharacter(
    660                 m_item.string[m_item.item.pos + endOfRun], false).fontData;
    661             if (nextGlyphData != glyphData)
    662                 break;
    663         }
    664         m_item.item.length = endOfRun;
    665         m_indexOfNextScriptRun = m_item.item.pos + endOfRun;
    666     }
    667 
    668     setupFontForScriptRun();
    669     shapeGlyphs();
    670     setGlyphPositions(rtl());
    671 
    672     return true;
    673 }
    727 void TextRunWalker::setupFontForScriptRun()
    728 {
    729     const FontData* fontData = m_font->glyphDataForCharacter(m_run[0], false).fontData;
    730     const FontPlatformData& platformData =
    731         fontData->fontDataForCharacter(' ')->platformData();
    732     const FontPlatformData* complexPlatformData = setupComplexFont(m_item.item.script, platformData);
    733 
    734     m_item.face = complexPlatformData->harfbuzzFace();
    735     m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData);
    736 
    737     int size = complexPlatformData->size();
    738     m_item.font->x_ppem = size;
    739     m_item.font->y_ppem = size;
    740     // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format.
    741     const int devicePixelFraction = 64;
    742     const int multiplyFor16Dot16 = 1 << 16;
    743     int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits();
    744     m_item.font->x_scale = scale;
    745     m_item.font->y_scale = scale;
    746 }