void Tick() { NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeLibTick, EA::WebKit::kVProcessStatusStarted, 0); SET_AUTOFPUPRECISION(EA::WebKit::kFPUPrecisionExtended); SET_AUTO_COLLECTOR_STACK_BASE(); EAWEBKIT_THREAD_CHECK(); EAWWBKIT_INIT_CHECK(); WTF::dispatchFunctionsFromMainThread(); // This is required for any children threads to work, for example, web workers. WebCore::ResourceHandleManager::sharedInstance()->TickDownload(); NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeTransportTick, EA::WebKit::kVProcessStatusStarted, 0); WebCore::ResourceHandleManager::sharedInstance()->TickTransportHandlers(); if(SocketTransportHandler* pSocketTxHandler = EA::WebKit::GetSocketTransportHandler()) pSocketTxHandler->Tick(); NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeTransportTick, EA::WebKit::kVProcessStatusEnded, 0); WebCore::fireTimerIfNeeded(); NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeLibTick, EA::WebKit::kVProcessStatusEnded, 0); }
JSValue* ScriptController::evaluate(const String& filename, int baseLine, const String& str) { // 11/09/09 CSidhall - Added notify process start to user NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeScript, EA::WebKit::kVProcessStatusStarted); // evaluate code. Returns the JS return value or 0 // if there was none, an error occured or the type couldn't be converted. initScriptIfNeeded(); // inlineCode is true for <a href="javascript:doSomething()"> // and false for <script>doSomething()</script>. Check if it has the // expected value in all cases. // See smart window.open policy for where this is used. ExecState* exec = m_windowShell->window()->globalExec(); m_processingInlineCode = filename.isNull(); JSLock lock; // Evaluating the JavaScript could cause the frame to be deallocated // so we start the keep alive timer here. m_frame->keepAlive(); m_windowShell->window()->startTimeoutCheck(); Completion comp = Interpreter::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), filename, baseLine, StringSourceProvider::create(str), m_windowShell); m_windowShell->window()->stopTimeoutCheck(); NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeScript, EA::WebKit::kVProcessStatusEnded); if (comp.complType() == Normal || comp.complType() == ReturnValue) { m_processingInlineCode = false; return comp.value(); } if (comp.complType() == Throw) { UString errorMessage = comp.value()->toString(exec); int lineNumber = comp.value()->toObject(exec)->get(exec, Identifier(exec, "line"))->toInt32(exec); UString sourceURL = comp.value()->toObject(exec)->get(exec, Identifier(exec, "sourceURL"))->toString(exec); m_frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, errorMessage, lineNumber, sourceURL); } m_processingInlineCode = false; return 0; }
FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName, bool checkingAlternateName) { NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeFontLoading, EA::WebKit::kVProcessStatusStarted); if (!gFontPlatformDataCache) { gFontPlatformDataCache = new FontPlatformDataCache; platformInit(); } FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(), fontDescription.usePrinterFont(), fontDescription.renderingMode()); FontPlatformData* result = 0; bool foundResult; FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key); if (it == gFontPlatformDataCache->end()) { result = createFontPlatformData(fontDescription, familyName); if(result) gFontPlatformDataCache->set(key, result); foundResult = result; } else { result = it->second; foundResult = true; } if (!foundResult && !checkingAlternateName) { // We were unable to find a font. We have a small set of fonts that we alias to other names, // e.g., Arial/Helvetica, Courier/Courier New, etc. Try looking up the font under the aliased name. const AtomicString* pAlternateName = alternateFamilyName(familyName); if (!pAlternateName->isEmpty()) result = getCachedFontPlatformData(fontDescription, *pAlternateName, true); if (result) { gFontPlatformDataCache->set(key, new FontPlatformData(*result)); // Cache the result under the old name. } } NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeFontLoading, EA::WebKit::kVProcessStatusEnded); return result; }
// We need to draw the glyphBuffer glyphs/advances with the pSimpleFontData font onto the // pGraphicsContext pSurface. We draw glyphCount glyphs starting at the glyphIndexBegin. void Font::drawGlyphs(GraphicsContext* pGraphicsContext, const SimpleFontData* pSimpleFontData, const GlyphBuffer& glyphBuffer, int glyphIndexBegin, int glyphCount, const FloatPoint& point) const { // 11/09/09 CSidhall Added notify start of process to user NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeDrawGlyph, EA::WebKit::kVProcessStatusStarted); #if defined(EA_DEBUG) && defined(AUTHOR_PPEDRIANA_DISABLED) && defined(EA_PLATFORM_WINDOWS) TraceGlyphBufferToString(pSimpleFontData, glyphBuffer, glyphIndexBegin, glyphCount, point); #endif GlyphBufferGlyph* glyphs = const_cast<GlyphBufferGlyph*>(glyphBuffer.glyphs(glyphIndexBegin)); float offset = 0; int x_offset = 0; EA::Internal::IFont* pFont = pSimpleFontData->m_font.mpFont; EA::Internal::IGlyphCache* pGlyphCache = EA::WebKit::GetGlyphCache(); EAW_ASSERT_MSG(pGlyphCache, "GlyphCache is not set"); if(!pGlyphCache) { NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeDrawGlyph, EA::WebKit::kVProcessStatusEnded); return; } EA::Internal::ITextureInfo* pTI = pGlyphCache->GetTextureInfo(0); // Right now we hard-code usage of what is the only texture. EAW_ASSERT_MSG(pTI, "GlyphCache is not initialized with enough number of textures"); if(!pTI) { NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeDrawGlyph, EA::WebKit::kVProcessStatusEnded); return; } const int32_t textureSize = (int32_t)pTI->GetSize(); EA::Internal::IGlyphTextureInfo gti; EA::Internal::GlyphMetrics glyphMetrics; GlyphDrawInfoArray gdiArray((size_t)(unsigned)glyphCount); // Walk through the list of glyphs and build up render info for each one. for (int i = 0; i < glyphCount; i++) { EA::Internal::GlyphId g = glyphs[i]; if(!pFont->GetGlyphMetrics(g, glyphMetrics)) { EAW_ASSERT_MSG(false, "Font::drawGlyphs: invalid glyph/Font combo."); pFont->GetGlyphIds(L"?", 1, &g, true); pFont->GetGlyphMetrics(g, glyphMetrics); } if(!pGlyphCache->GetGlyphTextureInfo(pFont, g, gti)) { const EA::Internal::GlyphBitmap* pGlyphBitmap; if(pFont->RenderGlyphBitmap(&pGlyphBitmap, g)) { if(pGlyphCache->AddGlyphTexture(pFont, g, pGlyphBitmap->mpData, pGlyphBitmap->mnWidth, pGlyphBitmap->mnHeight, pGlyphBitmap->mnStride, (uint32_t)pGlyphBitmap->mBitmapFormat, gti)) { pGlyphCache->EndUpdate(gti.mpTextureInfo); } else { EAW_ASSERT_MSG(false, "Font::drawGlyphs: AddGlyphTexture failed."); gti.mX1 = gti.mX2 = 0; // Make this an empty glyph. Normally this should never execute. } pFont->DoneGlyphBitmap(pGlyphBitmap); } else { EAW_ASSERT_MSG(false, "Font::drawGlyphs: invalid glyph/Font combo."); gti.mX1 = gti.mX2 = 0; // Make this an empty glyph. Normally this should never execute. } } // Apply kerning. // Note by Paul Pedriana: Can we really apply kerning here at the render stage without it looking // wrong? It seems to me this cannot work unless kerning is also taken into account at the // layout stage. To do: See if in fact kerning is taken into account at the layout stage. EA::Internal::Kerning kerning; if((i > 0) && pFont->GetKerning(glyphs[i - 1], g, kerning, 0)) offset += kerning.mfKernX; // The values we calculate here are relative to the current pen position at the // baseline position of [xoffset, 0], where +X is rightward and +Y is upward. gdiArray[i].x1 = (int)(offset + glyphMetrics.mfHBearingX); gdiArray[i].x2 = (int)(offset + glyphMetrics.mfHBearingX + glyphMetrics.mfSizeX); gdiArray[i].y1 = (int)(glyphMetrics.mfHBearingY); gdiArray[i].y2 = (int)(glyphMetrics.mfHBearingY - glyphMetrics.mfSizeY); gdiArray[i].tx = (int)(gti.mX1 * textureSize); // Convert [0..1] to [0..textureSize] gdiArray[i].ty = (int)(gti.mY1 * textureSize); // advanceAt should return a value that is usually equivalent to glyphMetrics.mfHAdvanceX, at least // for most simple Western text. A case where it would be different would be Arabic combining glyphs, // and custom kerning, though kerning adjustments are handled above. offset += glyphBuffer.advanceAt(glyphIndexBegin + i); // Free wrapper if(gti.mpTextureInfo) gti.mpTextureInfo->DestroyWrapper(); } // Find the X and Y minima and maxima of the glyph boxes. // To do: We can improve the efficiency of this code in a couple of ways, including moving the // min/max tests up into the glyphMetrics code above. int xMin = gdiArray[0].x1; int xMax = gdiArray[0].x2; int yMin = gdiArray[0].y2; // y2 is min because y goes upward. int yMax = gdiArray[0].y1; for (GlyphDrawInfoArray::const_iterator it = gdiArray.begin(); it != gdiArray.end(); ++it) { const GlyphDrawInfo& gdi = *it; // We assume tha x1 is always <= x2. if (gdi.x1 < xMin) xMin = gdi.x1; if (gdi.x2 > xMax) xMax = gdi.x2; // if (gdi.y1 < yMin) // We normally don't need this check, because y2 will usually (or always?) be less than y1. // yMin = gdi.y1; if (gdi.y2 < yMin) yMin = gdi.y2; if (gdi.y1 > yMax) yMax = gdi.y1; // if (gdi.y2 > yMax) // We normally don't need this check, because y1 will usually (or always?) be greater than y2. // yMax = gdi.y2; } const uint16_t destWidth = (abs(xMin) + xMax); // abs(xMin) because it's possible the left of the first glyph is to the left of the origin. Note by Paul Pedriana: Shouldn't this instead be (xMax - min(xMin, 0))? const uint16_t destHeight = (yMax - yMin); if(destWidth && destHeight) // (If we are drawing just space chars (which often happens), then destWidth and/or destHeight will be zero) { // Question by Paul Pedriana: What is the following code doing? I copied this from the // WebKit Freetype equivalent of this function assuming it must be useful. It seems to // me that it is chopping off any glyph pixels to the left of zero. This is probably // going to usually be OK, because it is abnormal for the first char of just about any // written language to be a combining char (and thus drawn to the left of the pen position). if (gdiArray[0].x1 < 0) { x_offset = gdiArray[0].x1; gdiArray[0].x1 = 0; } EA::Raster::Surface* const pSurface = pGraphicsContext->platformContext(); const Color penColor = pGraphicsContext->fillColor(); // Write the glyphs into a linear buffer. // To consider: See if it's possible to often get away with using stack space for this by // using Vector<uint32_t, N> in order to avoid a memory allocation. A typical // width is ~400 pixels and a typical height ~16 pixels, which is 25600 bytes. // So unless the string is small there won't be any benefit to this. Vector<uint32_t> glyphRGBABuffer(destWidth * destHeight); const int penA = penColor.alpha(); const int penR = penColor.red(); const int penG = penColor.green(); const int penB = penColor.blue(); const int penRGB = (penR << 16) | (penG << 8) | penB; glyphRGBABuffer.fill(0); for (int i = 0; i < glyphCount; i++) { const GlyphDrawInfo& gdi = gdiArray[i]; const uint8_t* pGlyphAlpha = (pTI->GetData()) + (gdi.ty * pTI->GetStride()) + gdi.tx; const int yOffset = (destHeight + yMin) - gdi.y1; // Note by Arpit Baldeva: Old index calculation below caused a memory overrun(or I should say underrun on http://get.adobe.com/flashplayer/). // Basically, yOffset * destWidth) + gdi.x1 could end up being negative if the yOffset is 0 and gdi.x1 is negative. Since I do want // to make sure that index is positive, I just force it to be at least 0. There is not enough understanding about this code as of now // and Paul said that he would take a look at this along with other Font problems he is currently looking at. const int bufferIndex = (yOffset * destWidth) + gdi.x1; EAW_ASSERT_FORMATTED(bufferIndex>=0, "Buffer Index is negative. This would corrupt memory. yOffset:%d,destWidth:%u,gdi.x1:%d",yOffset,destWidth,gdi.x1); uint32_t* pDestColor = glyphRGBABuffer.data() + (bufferIndex >= 0 ? bufferIndex : 0);//Old Index calculation- (yOffset * destWidth) + gdi.x1; const int glyphWidth = (gdi.x2 - gdi.x1); const int glyphHeight = (gdi.y1 - gdi.y2); for (int y = 0; y < glyphHeight; ++y) { for (int x = 0; x < glyphWidth; ++x) { //+ 1/5/10 CSidhall - When building the text string texture map, kerning can make certain letters overlap and stomp over the alpha of previous letters so // we need to preserve texels that were aleady set. Should be able to OR herer because we have a clean buffer and penRGB is the same. // Old code: // pDestColor[x] = ((penA * pGlyphAlpha[x] / 255) << 24) | penRGB; // New code: pDestColor[x] |= ((penA * pGlyphAlpha[x] / 255) << 24) | penRGB; // -CS } pDestColor += destWidth; pGlyphAlpha += pTI->GetStride(); } } // It would probably be faster if we kept around a surface for multiple usage instead of // continually recreating this one. EA::Raster::Surface* const pGlyphSurface = EA::Raster::CreateSurface((void*)glyphRGBABuffer.data(), destWidth, destHeight, destWidth * 4, EA::Raster::kPixelFormatTypeARGB, false, false); EA::Raster::Rect rectSrc; EA::Raster::Rect rectDest; rectSrc.w = destWidth; rectSrc.h = destHeight; rectSrc.x = 0; rectSrc.y = 0; rectDest.x = (int)point.x() + x_offset + pGraphicsContext->origin().width(); rectDest.y = (int)point.y() - yMax + pGraphicsContext->origin().height(); if (pGraphicsContext->transparencyLayer() == 1.0) EA::Raster::Blit(pGlyphSurface, &rectSrc, pSurface, &rectDest); else { const float fTransparency = pGraphicsContext->transparencyLayer(); EA::Raster::Surface* const pSurfaceWithAlpha = EA::Raster::CreateTransparentSurface(pGlyphSurface, (int)(fTransparency * 255)); EA::Raster::Blit(pSurfaceWithAlpha, &rectSrc, pSurface, &rectDest); EA::Raster::DestroySurface(pSurfaceWithAlpha); } EA::Raster::DestroySurface(pGlyphSurface); } pTI->DestroyWrapper(); NOTIFY_PROCESS_STATUS(EA::WebKit::kVProcessTypeDrawGlyph, EA::WebKit::kVProcessStatusEnded); }