Tizen 앱 스토어에 회원 가입이 되는 것을 알았습니다.

단,아래 그림처럼 마켓은 아직 오픈이 안된 것처럼 보입니다. (아직 정식 출시한 폰도 없으니까요)


http://www.tizenstore.com/ 접속 화면

<http://www.tizenstore.com 접속화면>


하지만 http://seller.tizenstore.com 으로 접속하면 아래와 같은 화면을 볼 수 있습니다.


<http://seller.tizenstore.com 접속 화면>


오른쪽 상단에  Join Now 를 누르면 아래 화면이 뜹니다.

< Join Now >

이 화면에서 로그인할 수 있는 입력창 아래로 두가지 타입의 회원 가입 버튼이 있습니다.

"Register as Private Seller" 와 Register as a Corporate Seller입니다.

Private Seller는 개인을 의미하고 Coorporate Seller는 회사를 의미합니다.

이 화면에서 "Register as Private Seller"를 클릭하겠습니다.



<회원 가입 화면>

회원 가입 화면에서는 몇 가지 정보를 입력하면 됩니다.

비밀번호에 "Invalid password. Please re-enter."라는 경고가 나오면, 입력에 필요한 최소한의 조건을 만족하지 못했다는 뜻입니다. 대충 확인해보니 알파벳 최소 8자를 입력해야 하는 듯 합니다.


아래로 좀 더 내리면 약관과 개인정보 동의 상자이 있습니다. Country를 선택하면 자동으로 약관이 변합니다. (한국을 선택하면 한국어로 약관이 변합니다.)

어차피 동의해야 하니 동의 합니다.


<가입 축하 메시지(아직 가입이 끝나지 않았습니다.) >

이메일로 확인 요청 메일이 발송되었습니다. 가입시 입력한 이메일을 확인하면 "Welcome to Tizen Store Seller Office."이라는 메일이 와 있을 것입니다.

메일의 링크를 클릭하면 아래 화면이 나옵니다.


<진짜 가입 축하 화면>

이것으로 가입이 완료되었습니다.

저작자 표시
신고
Posted by 소혼
TAG Tizen

관련된 글들이 몇개 있지만, 최신 상황에 맞게 정리해보았습니다.


1. Download efl


최신 efl은 git을 통해 다운 받습니다.

git이 설치되어 있지 않으면 git부터 설치하시기 바랍니다.

sudo apt-get install git


다운로드 주소 및 명령어

git clone git://git.enlightenment.org/core/efl.git
git clone git://git.enlightenment.org/core/elementary.git

기타 다른 모듈들을 보시려면 http://git.enlightenment.org/ 를 참고하시면 됩니다.


2. build


빌드하려면 몇가지 패키지들이 필요합니다. 아래 패키지들을 설치합니다. (http://seoz.egloos.com/3936054 참조)

sudo apt-get install build-essential automake libtool ccache zlib1g-dev libfreetype6-dev libdbus-1-dev liblua5.1-0-dev g++ libxext-dev libxrender-dev libpng12-dev libxrandr-dev libfontconfig1-dev libxcb-shape0-dev libfribidi-dev libcurl4-openssl-dev libxcb-keysyms1-dev libjpeg-dev gettext autopoint libgif-dev libtiff5-dev libxp-dev libxtst-dev libgl1-mesa-dev libxinerama-dev libxdamage-dev libxcursor-dev libglib2.0-dev libxcomposite-dev libxss-dev libpulse-dev libsndfile-dev libudev-dev libblkid-dev libmount-dev libgstreamer0.10-dev check libgstreamer-plugins-base0.10-dev libbullet-dev libvlc-dev


efl 폴더로 이동하여 빌드합니다.

cd efl

./autogen.sh

make -j8 && sudo make install


elementary 폴더로 이동하여 빌드합니다.

cd elementary

./autogen.sh

make -j8 && sudo make install


elementary_test를 실행해 봅니다.

elementary_test


저작자 표시
신고

'Open Source > EFL' 카테고리의 다른 글

[TIZEN] 2.2 Emulator 실행하기  (0) 2013.08.01
[TIZEN] Tizen App store 등록하기  (0) 2013.08.01
[EFL] EFL build on ubuntu (13.04)  (1) 2013.07.24
Simple event test(mouse down/focus) using Evas  (0) 2012.09.03
[ecore] screen size 얻기  (0) 2012.08.15
[Elementary] 기본 코드  (0) 2012.08.04
Posted by 소혼
TAG EFL

이 이미지는 아래 URL과 동일

http://www.chromium.org/developers/class-diagram-webkit-webcore-to-chrome-browser




저작자 표시
신고
Posted by 소혼

이전에 작성한 linkElement, style element에 이어 media rule을 사용해 media query를 주었을 때 웹킷이 처리하는 과정을 정리해보고자 합니다.


이전글 1 : Media query in webkit(link Element)

이전글 2 : Media query in webkit(style element)


특히 이전글2는 반드시 읽으셔야 합니다.


사용할 예제는 이전글2에서 잠깐 보여드렸던 것과 동일합니다.

### html

<!doctype html>
<head>
<style>
@media screen and (min-width:300px) {
body { background-color:red; }
}
</style>
<body>
hello
</body>


시작 지점은 이전 예제의 밑에서 두번째 코드인 DocumentRuleSets::appendAuthorStyleSheets 입니다.

### c++ ; highlight : 21

void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, bool isViewSource, StyleResolver* resolver)
{
    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    unsigned size = styleSheets.size();
    for (unsigned i = firstNew; i < size; ++i) {
        CSSStyleSheet* cssSheet = styleSheets[i].get();
        ASSERT(!cssSheet->disabled());
        if (cssSheet->mediaQueries() && !medium->eval(cssSheet->mediaQueries(), resolver))
            continue;
        StyleSheetContents* sheet = cssSheet->contents();
#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
            // FIXME: Remove a dependency to calling a StyleResolver's member function.
            // If we can avoid calling resolver->ensureScopeResolver() here, we don't have to include "StyleResolver.h".
            // https://bugs.webkit.org/show_bug.cgi?id=108890
            resolver->ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *medium, resolver, scope);
            continue;
        }
#endif
        m_authorStyle->addRulesFromSheet(sheet, *medium, resolver);
        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
    }
    m_authorStyle->shrinkToFit();
    collectFeatures(isViewSource, resolver->scopeResolver());
}


현재 styleSheet에 mediaQuery가 있다면, 2번글에서와 같이 eval과정을 거쳐서 addRulesFromSheet를 수행할지 말지를 결정할 것입니다. [9, 21라인]

하지만, 이번 예제에서 stylesheet에는 mediaQuery가 없습니다. 따라서 addRulesFromSheet가 수행됩니다.


addRulesFromSheet는 다음과 같습니다.


### c++

void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope)
{  
    ASSERT(sheet);                                                                                          
   
    const Vector<RefPtr<StyleRuleImport> >& importRules = sheet->importRules();                             
    for (unsigned i = 0; i < importRules.size(); ++i) {
        StyleRuleImport* importRule = importRules[i].get();
        if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), resolver)))
            addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope);                           
    }                                                                                                       
                                                                                                            
    bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL());
    AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0) | (!scope ? RuleCanUseFastCheckSelector : 0));
   
    addChildRules(sheet->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);   
                                                                                                            
    if (m_autoShrinkToFitEnabled)
        shrinkToFit();                                                                                      
}

sheet의 import rule들을 모두 순회하며, import rule의 media query를 확인, 있으면, 해당 import rule의 styleSheet를 위해 addRulesFromSheet를 호출합니다.

여기서는  import rule도 없으므로 지나가면 addChildRules라는 함수에서 실제 childRules들을 반영합니다. 이 함수의 인자에도 medium이 있는 것을 볼 수 있습니다.


### c++ ; highlight : [11, 13]

void RuleSet::addChildRules(const Vector<RefPtr<StyleRuleBase> >& rules, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope, bool hasDocumentSecurityOrigin, AddRuleFlags addRuleFlags)
{
    for (unsigned i = 0; i < rules.size(); ++i) {
        StyleRuleBase* rule = rules[i].get();

        if (rule->isStyleRule()) {
            StyleRule* styleRule = static_cast<StyleRule*>(rule);
            addStyleRule(styleRule, addRuleFlags);
        } else if (rule->isPageRule())
            addPageRule(static_cast<StyleRulePage*>(rule));
        else if (rule->isMediaRule()) {
            StyleRuleMedia* mediaRule = static_cast<StyleRuleMedia*>(rule);
            if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver)))
                addChildRules(mediaRule->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);
        } else if (rule->isFontFaceRule() && resolver) {
            // Add this font face to our set.
            // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
            if (scope)
                continue;
            const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(rule);
            resolver->fontSelector()->addFontFaceRule(fontFaceRule);
            resolver->invalidateMatchedPropertiesCache();
        } else if (rule->isKeyframesRule() && resolver) {
            // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
            if (scope)
                continue;
            resolver->addKeyframeStyle(static_cast<StyleRuleKeyframes*>(rule));
        }
#if ENABLE(CSS_REGIONS)
        else if (rule->isRegionRule() && resolver) {
            // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment.
            if (scope)
                continue;
            addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin);
        }
#endif
#if ENABLE(SHADOW_DOM)
        else if (rule->isHostRule())
            resolver->addHostRule(static_cast<StyleRuleHost*>(rule), hasDocumentSecurityOrigin, scope);
#endif
#if ENABLE(CSS_DEVICE_ADAPTATION)
        else if (rule->isViewportRule() && resolver) {
            // @viewport should not be scoped.
            if (scope)
                continue;
            resolver->viewportStyleResolver()->addViewportRule(static_cast<StyleRuleViewport*>(rule));
        }
#endif
#if ENABLE(CSS3_CONDITIONAL_RULES)
        else if (rule->isSupportsRule() && static_cast<StyleRuleSupports*>(rule)->conditionIsSupported())
            addChildRules(static_cast<StyleRuleSupports*>(rule)->childRules(), medium, resolver, scope, hasDocumentSecurityOrigin, addRuleFlags);

#endif

    }

}

다양한 CSS rule들을 처리하는 코드 가운데 media rule에 관한 코드를 발견하실 수 있습니다. [11라인]



media query를 발생시키는 코드들은 다 살펴보았지만, 2번글 마지막에서 잠깐 언급했던 것과 같이, viewport와 관련된 media query는 화면의 크기등이 바뀌었을 때 다시 계산할 필요가 있습니다.


예를 들어 webview를 resize하는 경우, FrameView의 size가 변경되어 FrameView::setFrameRect가 호출될 것입니다.


### c++ ; highlight : [33, 34, 35, 36, 37]

void FrameView::setFrameRect(const IntRect& newRect)
{
    IntRect oldRect = frameRect();
    if (newRect == oldRect)              
        return;
       
#if ENABLE(TEXT_AUTOSIZING)
    // Autosized font sizes depend on the width of the viewing area.
    if (newRect.width() != oldRect.width()) {
        Page* page = m_frame ? m_frame->page() : 0;
        if (page && page->mainFrame() == m_frame && page->settings()->textAutosizingEnabled()) {
            for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())        
                m_frame->document()->textAutosizer()->recalculateMultipliers();
        }                
    }
#endif

    ScrollView::setFrameRect(newRect);

    updateScrollableAreaSet();

    RenderView* renderView = this->renderView();

#if USE(ACCELERATED_COMPOSITING)
    if (renderView) {
        if (renderView->usesCompositing())
            renderView->compositor()->frameViewDidChangeSize();
    }
#endif

    Document* document = m_frame ? m_frame->document() : 0;

    // Viewport-dependent media queries may cause us to need completely different style information.
    if (document && document->styleResolverIfExists() && document->styleResolverIfExists()->affectedByViewportChange()) {
        document->styleResolverChanged(DeferRecalcStyle);
        InspectorInstrumentation::mediaQueryResultChanged(document);
    }

    sendResizeEventIfNeeded();
}

document객체에 있는 styleResolver의 affectedByViewportChange를 통해 media query의 결과가 바뀌었는지 보고[34 라인],

바뀌었다면, styleResolverChanged를 다시 불러줍니다.[35라인]


affectedByViewportChange는 아래와 같습니다.


### c++

bool StyleResolver::affectedByViewportChange() const
{
    unsigned s = m_viewportDependentMediaQueryResults.size();
    for (unsigned i = 0; i < s; i++) {
        if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
            return true;
    }
    return false;
}


저작자 표시 비영리 변경 금지
신고
Posted by 소혼

WebKit/Efl (ewebkit)을 빌드하는 방법은 다음 글을 참고해주세요.

(http://bunhere.tistory.com/387)


webkit은 빌드에 너무 시간이 많이 걸려서 패키지로 만들어서 공유해두어야겠다는 생각이 들었습니다.


webkit1/efl (이하 ewebkit) 패키지와 webkit2/efl(이하 ewebkit2)를 만들기 위해 debian폴더를 만들었습니다.

git clone https://github.com/bunhere/ewebkit-debian.git


ubuntu 12.10 (64비트)를 사용하시는 경우, output 폴더 아래 패키지를 다운받아 설치해주시면 됩니다. 또는 아래 첨부 deb를 클릭하셔도 됩니다.(gdrive)


설치하는 법은 dpkg -i 파일명 입니다.

기존에 설치한 패키지를 지우려면 dpkg -r 패키지명 치시면 됩니다.

1. 아직 불완전합니다. efl, edbus, harfbuzz를 포함한 다수의 dep를 해결해주지 않습니다.

     efl 관련해서는 efl.or.kr을,   edbus, harfbuzz는 위 글을 참고하세요

2. ewebkit2 도 조만간 준비하겠습니다.

3.이 글을 계속 업데이트하도록 하겠습니다.


* 현재 ewebkit패키지와 ewebkit2 패키지는 공통의 파일(theme, resource)를 포함하고 있어, 같이 설치가 되지 않을 것입니다.

* 불편하더라도 번갈아가면서 설치하거나 강제로 설치해야 합니다.


------------- ewebkit -------------------------

r146585 (09/04/22)

libewebkit_0.1_amd64.deb

libewebkit-dev_0.1_amd64.deb

------------- ewebkit2 -------------------------

r146860 (13/03/26)

libewebkit2_0.1_amd64.deb

libewebkit2-dev_0.1_amd64.deb

저작자 표시
신고
Posted by 소혼
TAG ewebkit

이전에 작성한 linkElement에 이어 style element로 media query를 주었을 때 웹킷이 처리하는 과정을 정리해보고자 합니다.

style element에 대한 처리를 알려면, webkit이 style element을 처리하는 전반적인 플로우를 이해해야 합니다.

하지만, 여기서는 되도록 media query에 집중해서 설명하려고 노력할 생각입니다.


이전글 : Media query in webkit(link Element)

다음글 : Media query in webkit(import/media rule)


이번에 다룰 예제는 아래와 같습니다.


### html

<!doctype html>
<head>
<style media="screen and (min-width:300px)">
body { background-color:red; }
</style>
<body>
hello
</body>

HTML specification에서 style element를 보면 attribute로 media를 지정할 수 있습니다.


먼저 이 코드를 크롬으로 로드하여 inspector를 통해 document.styleSheets를 보도록 하겠습니다.


StyleSheetList에 한 개의 stylesheet가 있고, 0번째 CSSStyleSheet에는 cssRules, disabled, href, media, 등등이 있습니다.

MediaList타입의 media 프로퍼티에는 style element의 attribute로 넘긴 media query 정보가 들어 있음을 알 수 있습니다.

CSSRuleList타입의 cssRules에는 1개의 CSSStyleRule이 있고 이 안에 지정한 스타일 정보가 들어있음을 알 수 있습니다.


여기서 표현되는 CSSStyleSheet, CSSRuleList, CSSStyleRul은 웹킷 내부에 동일한 이름의 클래스와 매칭됩니다.


이번 글에서 다루진 않겠지만 참고 삼아, 예제를 조금 고쳐보겠습니다. 이번에는 @media rule을 사용한 경우입니다.


### html

<!doctype html>
<head>
<style>
@media screen and (min-width:300px) {
body { background-color:red; }
}
</style>
<body>
hello
</body>




이렇게 변경하면 CSSStyleSheet가 가진 media 프로퍼티에는 아무런 값이 존재하지 않습니다.

대신 cssRules 가 직접 CSSStyleRule을 갖는 것이 아니라, CSSMediaRule을 갖는 것을 알 수 있습니다. CSSMediaRule이  CSSStyleRule을 갖습니다.


[WebKit Internal]

WebKit에서 Style tag를 담당하는 클래스는 HTMLStyleElement와 StyleElement입니다.

HTMLStyleElement는 StyleElement를 상속받습니다. (class HTMLStyleElement : public HTMLElement, private StyleElement)

SVGStyleElement와 공용으로 쓸 수 있는 기능들이 StyleElement안에 있는듯 합니다.


먼저 </style>태그를  만나 읽게 되면  HTMLElement들은 finishParsingChildren을 호출합니다.

HTMLStyleElement 도 해당 함수의 구현을 갖고 있습니다.


### c++

void HTMLStyleElement::finishParsingChildren()
{
    StyleElement::finishParsingChildren(this);
    HTMLElement::finishParsingChildren();
}

여기서 관심을 갖는 부분은 StyleElement입니다.


### c++ ; highlight : [29, 34]

void StyleElement::finishParsingChildren(Element* element)
{  
    ASSERT(element);
    process(element);
    m_createdByParser = false;
}

void StyleElement::process(Element* e)
{  
    if (!e || !e->inDocument())
        return;
   
    unsigned resultLength = 0;
    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
        if (isValidStyleChild(c)) {
            unsigned length = c->nodeValue().length();
            if (length > std::numeric_limits<unsigned>::max() - resultLength) {
                createSheet(e, m_startLineNumber, "");
                return;
            }
            resultLength += length;
        }
    }
    StringBuilder sheetText;
    sheetText.reserveCapacity(resultLength);
   
    for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
        if (isValidStyleChild(c)) {
            sheetText.append(c->nodeValue());
        }
    }
    ASSERT(sheetText.length() == resultLength);
   
    createSheet(e, m_startLineNumber, sheetText.toString());
}

StyleElement::finishParsingChildren가 하는 일도 간단히 process()를 부르는 일이 전부입니다.

process()는

1. parsing이 끝났을때(finishParsingChildren),

2. StyleElement가 document에 insert 되었을 때(insertIntoDocument)

3. 자식 노드들이 바뀌었을 때(childrendChanged)

호출됩니다.


process()안을 보시면, child node 가운데 validStyleChild만 찾아서 해당하는 sheetText에 추가하는 것을 알 수 있습니다.(29 line)

위 예제에서는 하나의 노드(TextNode)만을 가지고

값(nodeValue)은 "

body { background-color:red; }

" 입니다. (<style>부터 </style>까지 이기 때문에 위 예제에서는 앞뒤로 newline이 있습니다.)


### c++

static bool isValidStyleChild(Node* node)
{  
    ASSERT(node);
    Node::NodeType nodeType = node->nodeType();
    return nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE;
}

validStyleChild는 단순히 TEXT_NODE와 CDATA_SECTION_NODE 인지 여부만 체크합니다.


사실상 핵심은 sheet를 만드는 것입니다.(StyleElement::process의 34 line)

StyleElement::process는 엘리먼트(e)와 시작라인, sheetText 문자열(valid한 child node들의 문자열)을 createSheet에게 넘겨줍니다.


### c++ ; highlight: [6,7,8,9,10, 17]

void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, const String& text)
{            
    ASSERT(e);             
    ASSERT(e->inDocument());          
    Document* document = e->document();
    if (m_sheet) {              
        if (m_sheet->isLoading())                                 
            document->styleSheetCollection()->removePendingSheet();
        clearSheet();
    }
                                                          
    // If type is empty or CSS, this is a CSS style sheet.
    const AtomicString& type = this->type();                                       
    if (document->contentSecurityPolicy()->allowInlineStyle(e->document()->url(), startLineNumber) && isCSS(e, type)) {
        RefPtr<MediaQuerySet> mediaQueries;
        if (e->isHTMLElement())
            mediaQueries = MediaQuerySet::createAllowingDescriptionSyntax(media());
        else
            mediaQueries = MediaQuerySet::create(media());
           
        MediaQueryEvaluator screenEval("screen", true);
        MediaQueryEvaluator printEval("print", true);
        if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {

            // ... 생략, 아래에서 계속
        }  
    }
               
    if (m_sheet)
        m_sheet->contents()->checkLoaded();
}

먼저 기존에 만든 CSSStyleSheet이 있는지 확인하고, 있다면 제거합니다. (6-10 line). 이 때 CSSStyleSheet이 로딩중이면 제거합니다.(8line)

StyleElement가 가진 CSSStyleSheet이 로딩중인 케이스는 import rule을 생각하시면 됩니다.


현재 StyleElement는 HTMLStyleElement 에서 this를 받아왔기 때문에 MediaQuerySet::createAllowingDescriptionSyntax(media())를 호출합니다.(17 line)


Media query in webkit(linkElement)를 읽으신 분들은 MediaQueryEvaluator을 만들때 추가로 요구하는 값들이 있었다는 것을 기억해주시기 바랍니다.

FrameView의 mediaType, frame, documentStyle입니다. 여기서는 FrameView의 media type대신 "screen"과 "print" 두개의 MediaQueryEvaluator를 만들고 있고 다른 값들은 넘겨주지 않습니다. 

다른 값들이 없으면 media feature를 확인하는 것이 불가능합니다.

이전 글에서 colorMediaFeatureEval의 구현을 보시면, frame을 이용하여 screenDepth를 구하고 있는 것을 알 수 있습니다.


여기서는 대신 두 번째 인자로 true를 넘겨주고 있습니다. 이 값은 MediaQueryEvaluator의 멤버인 m_expResult의 값이 됩니다.

그리고 MediaQueryEvaluator::eval(MediaQueryExp*) const을 다시 보시면,

### c++ ; hilight : [3, 4]

bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
{
    if (!m_frame || !m_style)
        return m_expResult;

    if (!expr->isValid())
        return false;

    if (!gFunctionMap)
        createFunctionMap();

    // call the media feature evaluation function. Assume no prefix
    // and let trampoline functions override the prefix if prefix is
    // used
    EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
    if (func)
        return func(expr->value(), m_style.get(), m_frame, NoPrefix);

    return false;
}

frame과 style의 값이 없을 때 m_expResult의 값을 반환합니다.(4 line)

즉, StyleElement::createSheet에서는 media type만 확인하고 true를 반환합니다.


### c++ ; highlight : [ 7, 10, 11, 13 ]

void StyleElement::createSheet(Element* e, WTF::OrdinalNumber startLineNumber, const String& text)
{
        // ... 생략, 위에서 계속
        MediaQueryEvaluator screenEval("screen", true);
        MediaQueryEvaluator printEval("print", true);
        if (screenEval.eval(mediaQueries.get()) || printEval.eval(mediaQueries.get())) {
            document->styleSheetCollection()->addPendingSheet();
            m_loading = true;

            m_sheet = CSSStyleSheet::createInline(e, KURL(), document->inputEncoding());
            m_sheet->setMediaQueries(mediaQueries.release());
            m_sheet->setTitle(e->title());
            m_sheet->contents()->parseStringAtLine(text, startLineNumber.zeroBasedInt());

            m_loading = false;
        }
    }

    if (m_sheet)
        m_sheet->contents()->checkLoaded();
}

media type이 screen이나 print를 포함한다면, StyleElement::createSheet의 7-15 line에서 CSSStyleSheet를 만듭니다.
먼저 document에 pending된 스타일 시트가 있음을 알립니다.(7 line). document에 pending된 스타일 시트가 있으면 웹코어는 layout을 주기적으로 스케줄링합니다.


그리고, CSSStyleSheet::createInline을 통해 stylesheet를 만듭니다.(9 line) 이 때, CSSStyleSheet::createInline은 StyleSheetContents를 만드는데 여기가 parsing된 결과물(CSSRule)이 저장되는 곳입니다.,


이 후, media query를 설정후(10 line), 넘겨받은 text data의 파싱을 수행합니다. (11 line)


parsing이 끝나면, checkLoaded를 통해 style을 적용할지를 결정합니다.

### c++ ; highlight : 23

void StyleSheetContents::checkLoaded()
{                                                                                  
    if (isLoading())                                                               
        return;                                                                    
                                                                                   
    RefPtr<StyleSheetContents> protect(this);                                      
                                                                                   
    // Avoid |this| being deleted by scripts that run via                          
    // ScriptableDocumentParser::executeScriptsWaitingForStylesheets().            
    // See <rdar://problem/6622300>.                                               
    RefPtr<StyleSheetContents> protector(this);                                    
    StyleSheetContents* parentSheet = parentStyleSheet();                          
    if (parentSheet) {                                                             
        parentSheet->checkLoaded();                                                
        m_loadCompleted = true;                                                    
        return;                                                                    
    }                                                                              
    RefPtr<Node> ownerNode = singleOwnerNode();                                    
    if (!ownerNode) {                                                              
        m_loadCompleted = true;                                                    
        return;                                                                    
    }                                                                              
    m_loadCompleted = ownerNode->sheetLoaded();                                    
    if (m_loadCompleted)                                                           
        ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur);
}

먼저 자신이 로딩중이면, return합니다 (3 line). 예제에서는 로딩할 것이 없으므로 파싱이 끝나면 로딩도 끝납니다. 다음엔 parentSheet가 있으면 parentSheet를 check하는데 여기서는 parentSheet가 없으므로 ownerNode(StyleElement)의 sheetLoaded를 호출합니다. (23 line)


### c++

bool StyleElement::sheetLoaded(Document* document)
{                                                                                  
    ASSERT(document);                                                              
    if (isLoading())
        return false;                                                              
   
    document->styleSheetCollection()->removePendingSheet();                        
    return true;                                                                   
}

pendingSheet를 제거합니다.


### c++ ; highlight : [14, 22]

// This method is called whenever a top-level stylesheet has finished loading.
void DocumentStyleSheetCollection::removePendingSheet(RemovePendingSheetNotificationType notification)
{  
    // Make sure we knew this sheet was pending, and that our count isn't out of sync.
    ASSERT(m_pendingStylesheets > 0);

    m_pendingStylesheets--;
    
#ifdef INSTRUMENT_LAYOUT_SCHEDULING                                                
    if (!ownerElement())                                                           
        printf("Stylesheet loaded at time %d. %d stylesheets still remain.\n", elapsedTime(), m_pendingStylesheets);
#endif 
   
    if (m_pendingStylesheets)
        return;

    if (notification == RemovePendingSheetNotifyLater) {
        m_document->setNeedsNotifyRemoveAllPendingStylesheet();                    
        return;
    }
   
    m_document->didRemoveAllPendingStylesheet();                                   
}

pendingStyleSheets가 더이상 없다면(14 line), didRemoveAllPendingStylesheet를 호출합니다.


### c++ ; highlight : 5

void Document::didRemoveAllPendingStylesheet()                                     
{  
    m_needsNotifyRemoveAllPendingStylesheet = false;

    styleResolverChanged(RecalcStyleIfNeeded);
   
    if (ScriptableDocumentParser* parser = scriptableDocumentParser())
        parser->executeScriptsWaitingForStylesheets();
   
    if (m_gotoAnchorNeededAfterStylesheetsLoad && view())
        view()->scrollToFragment(m_url);
}

StyleResolve가 변경되었음을 알려줍니다.(5 line)


### c++ ; highlight : 19

void Document::styleResolverChanged(StyleResolverUpdateFlag updateFlag)
{
    // Don't bother updating, since we haven't loaded all our style info yet
    // and haven't calculated the style selector for the first time.
    if (!attached() || (!m_didCalculateStyleResolver && !haveStylesheetsLoaded())) {
        m_styleResolver.clear();
        return;
    }
    m_didCalculateStyleResolver = true;

#ifdef INSTRUMENT_LAYOUT_SCHEDULING
    if (!ownerElement())
        printf("Beginning update of style selector at time %d.\n", elapsedTime());
#endif

    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded)
        ? DocumentStyleSheetCollection::OptimizedUpdate
        : DocumentStyleSheetCollection::FullUpdate;
    bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection->updateActiveStyleSheets(styleSheetUpdate);

    if (updateFlag == DeferRecalcStyle) {
        scheduleForcedStyleRecalc();
        return;
    }

    // ...

}

styleResolverChanged는 webkit이 layout을 다시 수행하게 되는 관문격에 해당하는 메소드입니다.

이 메소드에서 updateActiveStyleSheets가 호출되어 스타일 시트들을 업데이트 하게 됩니다. (19 line)


### c++ ; highlight : [16, 22, 35, 38]

bool DocumentStyleSheetCollection::updateActiveStyleSheets(UpdateFlag updateFlag)
{
    if (m_document->inStyleRecalc()) {
        // SVG <use> element may manage to invalidate style selector in the middle of a style recalc.
        // https://bugs.webkit.org/show_bug.cgi?id=54344
        // FIXME: This should be fixed in SVG and the call site replaced by ASSERT(!m_inStyleRecalc).
        m_needsUpdateActiveStylesheetsOnStyleRecalc = true;
        m_document->scheduleForcedStyleRecalc();
        return false;
       
    }
    if (!m_document->renderer() || !m_document->attached())
        return false;
       
    Vector<RefPtr<StyleSheet> > activeStyleSheets;
    collectActiveStyleSheets(activeStyleSheets);
   
    Vector<RefPtr<CSSStyleSheet> > activeCSSStyleSheets;
    activeCSSStyleSheets.append(injectedAuthorStyleSheets());
    activeCSSStyleSheets.append(documentAuthorStyleSheets());
    collectActiveCSSStyleSheetsFromSeamlessParents(activeCSSStyleSheets, m_document);
    filterEnabledCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
   
    StyleResolverUpdateType styleResolverUpdateType;
    bool requiresFullStyleRecalc;
    analyzeStyleSheetChange(updateFlag, activeCSSStyleSheets, styleResolverUpdateType, requiresFullStyleRecalc);


    if (styleResolverUpdateType == Reconstruct)
        m_document->clearStyleResolver();
    else {                                                                             
        StyleResolver* styleResolver = m_document->styleResolver();
        if (styleResolverUpdateType == Reset) {
            styleResolver->ruleSets().resetAuthorStyle();
            styleResolver->appendAuthorStyleSheets(0, activeCSSStyleSheets);
        } else {
            ASSERT(styleResolverUpdateType == Additive);                               
            styleResolver->appendAuthorStyleSheets(m_activeAuthorStyleSheets.size(), activeCSSStyleSheets);                                                                    
        }
        resetCSSFeatureFlags();
    }

    m_activeAuthorStyleSheets.swap(activeCSSStyleSheets);
    m_styleSheetsForStyleSheetList.swap(activeStyleSheets);

// ...

updateActiveStyleSheets도 많은 일을 수행하지만 일단, collectActiveStyleSheets를 호출합니다. (16 line)

아래서 코드를 보겠지만, activeStyleSheets를 통해 현재 page의 style sheet를 가져오게 됩니다.

여기에 filterEnabledCSSStyleSheets 함수를 통해 activeStyleSheets중에 사용할 수 있는 것들만 activeCSSStyleSheets로 옮깁니다. ( 22 line)
그리고 styleResolver->appendAuthorStyleSheets를 호출합니다. (35 or 38 line)



### c++ ; highlight : [8, 25, 64, 87]

void DocumentStyleSheetCollection::collectActiveStyleSheets(Vector<RefPtr<StyleSheet> >& sheets)
{
    if (m_document->settings() && !m_document->settings()->authorAndUserStylesEnabled())
        return;

    StyleSheetCandidateListHashSet::iterator begin = m_styleSheetCandidateNodes.begin();
    StyleSheetCandidateListHashSet::iterator end = m_styleSheetCandidateNodes.end();
    for (StyleSheetCandidateListHashSet::iterator it = begin; it != end; ++it) {
        Node* n = *it;
        StyleSheet* sheet = 0;
        if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) {
            // Processing instruction (XML documents only).
            // We don't support linking to embedded CSS stylesheets, see <https://bugs.webkit.org/show_bug.cgi?id=49281> for discussion.
            ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(n);
            sheet = pi->sheet();
#if ENABLE(XSLT)
            // Don't apply XSL transforms to already transformed documents -- <rdar://problem/4132806>
            if (pi->isXSL() && !m_document->transformSourceDocument()) {
                // Don't apply XSL transforms until loading is finished.
                if (!m_document->parsing())
                    m_document->applyXSLTransform(pi);
                return;
            }
#endif
        } else if ((n->isHTMLElement() && (n->hasTagName(linkTag) || n->hasTagName(styleTag)))
#if ENABLE(SVG)
                   ||  (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
#endif
                   ) {
            Element* e = static_cast<Element*>(n);
            AtomicString title = e->getAttribute(titleAttr);
            bool enabledViaScript = false;
            if (e->hasLocalName(linkTag)) {
                // <LINK> element
                HTMLLinkElement* linkElement = static_cast<HTMLLinkElement*>(n);
                if (linkElement->isDisabled())
                    continue;
                enabledViaScript = linkElement->isEnabledViaScript();
                if (linkElement->styleSheetIsLoading()) {
                    // it is loading but we should still decide which style sheet set to use
                    if (!enabledViaScript && !title.isEmpty() && m_preferredStylesheetSetName.isEmpty()) {
                        const AtomicString& rel = e->getAttribute(relAttr);
                        if (!rel.contains("alternate")) {
                            m_preferredStylesheetSetName = title;
                            m_selectedStylesheetSetName = title;
                        }
                    }
                    continue;
                }
                if (!linkElement->sheet())
                    title = nullAtom;
            }
            // Get the current preferred styleset. This is the
            // set of sheets that will be enabled.
#if ENABLE(SVG)
            if (n->isSVGElement() && n->hasTagName(SVGNames::styleTag))
                sheet = static_cast<SVGStyleElement*>(n)->sheet();
            else
#endif
            if (e->hasLocalName(linkTag))
                sheet = static_cast<HTMLLinkElement*>(n)->sheet();
            else
                // <STYLE> element
                sheet = static_cast<HTMLStyleElement*>(n)->sheet();
            // Check to see if this sheet belongs to a styleset
            // (thus making it PREFERRED or ALTERNATE rather than
            // PERSISTENT).
            AtomicString rel = e->getAttribute(relAttr);
            if (!enabledViaScript && !title.isEmpty()) {
                // Yes, we have a title.
                if (m_preferredStylesheetSetName.isEmpty()) {
                    // No preferred set has been established. If
                    // we are NOT an alternate sheet, then establish
                    // us as the preferred set. Otherwise, just ignore
                    // this sheet.
                    if (e->hasLocalName(styleTag) || !rel.contains("alternate"))
                        m_preferredStylesheetSetName = m_selectedStylesheetSetName = title;
                }
                if (title != m_preferredStylesheetSetName)
                    sheet = 0;
            }

            if (rel.contains("alternate") && title.isEmpty())
                sheet = 0;
        }
        if (sheet)
            sheets.append(sheet);
    }
}

CandidateNode들을 돌면서 style element의 sheet를 append합니다.


styleResolver->appendAuthorStyleSheets는 결국 DocumentRuleSets::appendAuthorStyleSheets를 호출합니다.

### c++ ; highlight : [9, 21]

void DocumentRuleSets::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets, MediaQueryEvaluator* medium, InspectorCSSOMWrappers& inspectorCSSOMWrappers, bool isViewSource, StyleResolver* resolver)
{
    // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    unsigned size = styleSheets.size();
    for (unsigned i = firstNew; i < size; ++i) {
        CSSStyleSheet* cssSheet = styleSheets[i].get();
        ASSERT(!cssSheet->disabled());
        if (cssSheet->mediaQueries() && !medium->eval(cssSheet->mediaQueries(), resolver))
            continue;
        StyleSheetContents* sheet = cssSheet->contents();
#if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
        if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
            // FIXME: Remove a dependency to calling a StyleResolver's member function.
            // If we can avoid calling resolver->ensureScopeResolver() here, we don't have to include "StyleResolver.h".
            // https://bugs.webkit.org/show_bug.cgi?id=108890
            resolver->ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *medium, resolver, scope);
            continue;
        }
#endif
        m_authorStyle->addRulesFromSheet(sheet, *medium, resolver);
        inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
    }
    m_authorStyle->shrinkToFit();
    collectFeatures(isViewSource, resolver->scopeResolver());
}

드디어 찾아헤매던 media query가 나왔습니다.( 9 line)

StyleResolver가 갖고 있던 m_medium을 받아 이 값을 각각의 CSSStyleSheet의 media query와 비교하여 매치 되는 스타일 시트만 rule에 추가됩니다. (21 line)

이 때 resolver의 값도 같이 넘어가는 것을 보실 수 있습니다.


resolver의 값이 있기 때문에 이제 viewport dependent여부를 확인할 수 있습니다.

### c++ ; highlight : [25, 26]

bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
{
    if (!querySet)
        return true;

    const Vector<OwnPtr<MediaQuery> >& queries = querySet->queryVector();
    if (!queries.size())
        return true; // empty query list evaluates to true

    // iterate over queries, stop if any of them eval to true (OR semantics)
    bool result = false;
    for (size_t i = 0; i < queries.size() && !result; ++i) {
        MediaQuery* query = queries[i].get();

        if (query->ignored())
            continue;

        if (mediaTypeMatch(query->mediaType())) {
            const Vector<OwnPtr<MediaQueryExp> >* exps = query->expressions();
            // iterate through expressions, stop if any of them eval to false
            // (AND semantics)
            size_t j = 0;
            for (; j < exps->size(); ++j) {
                bool exprResult = eval(exps->at(j).get());
                if (styleResolver && exps->at(j)->isViewportDependent())
                    styleResolver->addViewportDependentMediaQueryResult(exps->at(j).get(), exprResult);
                if (!exprResult)
                    break;
            }

            // assume true if we are at the end of the list,
            // otherwise assume false
            result = applyRestrictor(query->restrictor(), exps->size() == j);
        } else
            result = applyRestrictor(query->restrictor(), false);
    }

    return result;
}

Media query expression이 viewport dependent한지 체크합니다. 예제에서 width를 지정했으므로 viewport dependent합니다.

따라서 styleResolver에 해당 mediaQuery를 넘겨주게 따로 저장하고 있게 됩니다. ( 26 line )

이렇게 저장된 정보는 layout과정에서 다시 evaluation의 대상이 될 것입니다.


위에서 스타일 시트를 추가할 때 link element도 고려해서 추가하고 있었던 것을 기억하신다면,

이전글에서 설명한 것 외에 linke element에 대해서도 이 부분에서 한번 더 evaluation과정을 거치게 되고 이 때 viewportDependent도 체크하게 될 것입니다.

저작자 표시 비영리 변경 금지
신고
Posted by 소혼

[media query 간략 소개]

Media query는 media의 종류에 따라 특정 CSS 스타일을 적용하고자 할 때  사용하는 CSS 스펙 가운데 하나입니다.

(http://www.w3.org/TR/css3-mediaqueries/)



media query에 대한 article : http://html.nhncorp.com/blog/42284


다음글 : Media query in webkit (style element)

그 다음글 : Media query in webkit(import/media rule)







예를 들어 아래는 대표적인 media query의 예입니다. (이 글에서 코드리딩할 방법입니다.)

### html
<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css">
<link rel="stylesheet" type="text/css" media="print" href="serif.css">

screenprint는 가장 많이 알려진 미디어의 종류(type)입니다.


또는 아래처럼 쓸 수도 있습니다.

### css
@media screen {
 * { font-family: sans-serif }
}


또 @import rule을 사용하여 아래와 같은 방법도 있습니다.

### css

@import url(example.css) screen


style element 자체에도 media query를 사용할 수 있습니다.

### html

<style media="screen and (min-width:300px)">
body { background-color:red; }
</style>


media query라는 단어가 말하듯 단순히 media의 종류를 지정하는 것 뿐 아니라 간단한 형태의 조건을 줄 수도 있습니다.

자세한 내용은 위에 링크한 스펙을 참고하시기 바랍니다.


간단히 정리하면 다음과 같습니다.

  • 여러 media type을 지정하고 싶다면 , 를 사용합니다. (screen, print)
  • media에 추가로 특정 media feature만 적용되도록 제한하고 싶다면 media feature와 media value로 이루어지는 수식들을 and로 추가할 수 있습니다.
  • only, not과 같은 제한자를 가질 수 있습니다.


예를 들면, 아래와 같습니다.

### css

<link rel="stylesheet" media="speech and (min-device-width: 800px)" href="example.css" />



[WebKit internal]

일단 위 예제 1의 <link>의 경우부터 시작하겠습니다. (1번라인을 기준으로 설명하겠습니다.)

네트워크로부터 데이터를 가져와서 link 태그를 파싱하면 HTMLLinkElement를 만들게 됩니다.

그 다음 Attribute들을 파싱하기 위해 parseAttribute를 부릅니다.


### c++; highlight: [9, 10]

void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    if (name == relAttr) {
        m_relAttribute = LinkRelAttribute(value);
        process();
    } else if (name == hrefAttr) {
         // ...
    } else if (name == mediaAttr) {
        m_media = value.string().lower();
        process();
    } else if (name == disabledAttr)
         // ...
    else {
        if (name == titleAttr && m_sheet)
            m_sheet->setTitle(value);
        HTMLElement::parseAttribute(name, value);
    }
}

만약 현재 처리할 attribute가 media라면(9 line) value(screen)를 소문자로 변경하여 m_media에 넣고 process()를 호출합니다.


### c++; highlight:[10, 11, 12]

void HTMLLinkElement::process()
{
    // ...

    if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css")))
        && document()->frame() && m_url.isValid()) {

        // ...

        bool mediaQueryMatches = true;
        if (!m_media.isEmpty()) {
            RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(document());
            RefPtr<MediaQuerySet> media = MediaQuerySet::createAllowingDescriptionSyntax(m_media);
            MediaQueryEvaluator evaluator(document()->frame()->view()->mediaType(), document()->frame(), documentStyle.get());
            mediaQueryMatches = evaluator.eval(media.get());
        }

        // Don't hold up render tree construction and script execution on stylesheets
        // that are not needed for the rendering at the moment.
        bool blocking = mediaQueryMatches && !isAlternate();
        addPendingSheet(blocking ? Blocking : NonBlocking);

        // Load stylesheets that are not needed for the rendering immediately with low priority.
        ResourceLoadPriority priority = blocking ? ResourceLoadPriorityUnresolved : ResourceLoadPriorityVeryLow;
        CachedResourceRequest request(ResourceRequest(document()->completeURL(m_url)), charset, priority);
        request.setInitiator(this);
        m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request);

        if (m_cachedSheet)
            m_cachedSheet->addClient(this);
        else {
            // The request may have been denied if (for example) the stylesheet is local and the document is remote.
            m_loading = false;
            removePendingSheet();
        }

       // ...

}

기본적으로 mediaQueryMatches는 true 입니다.

그러나, m_media가 있다면, FrameView의 mediaType, frame, documentStyle과 비교하여 mediaQuery가 match되는지 확인합니다.(9-12 line)

MediaQueryEvaluator가 이 값들을 가지고 있다가 eval을 통해 비교할 것입니다. (12 line)


만약 match된다면, loader에게 정상적으로 로드요청을 하겠지만, 아니면, blocking되었다가 제거될 것입니다.


m_media는 간단하게는 screen과 같이 media type만 있을 수도 있지만, "screen and (color:1), projection" 과 같이 여러 media type들과 media feature로 이루어진 수식을 포함할지도 모릅니다.


따라서 MediaQueryEvaluator가 쉽게 계산할 수 있도록 MediaQuerySet::createAllowingDescriptionSyntax을 이용하여 media query set으로 변환합니다.(10 line)


### c++ : highlight: [7, 9, 15]

bool MediaQuerySet::parse(const String& mediaString)
{
    CSSParser parser(CSSStrictMode);

    Vector<OwnPtr<MediaQuery> > result;
    Vector<String> list;
    mediaString.split(',', list);
    for (unsigned i = 0; i < list.size(); ++i) {
        String medium = list[i].stripWhiteSpace();
        if (medium.isEmpty()) {
            if (!m_fallbackToDescriptor)
                return false;
            continue;
        }
        OwnPtr<MediaQuery> mediaQuery = parser.parseMediaQuery(medium);
        if (!mediaQuery) {
            if (!m_fallbackToDescriptor)
                return false;
            String mediaDescriptor = parseMediaDescriptor(medium);
            if (mediaDescriptor.isNull())
                continue;
            mediaQuery = adoptPtr(new MediaQuery(MediaQuery::None, mediaDescriptor, nullptr));
        }
        result.append(mediaQuery.release());
    }
    // ",,,," falls straight through, but is not valid unless fallback
    if (!m_fallbackToDescriptor && list.isEmpty()) {
        String strippedMediaString = mediaString.stripWhiteSpace();
        if (!strippedMediaString.isEmpty())
            return false;
    }
    m_queries.swap(result);
    return true;
}

createAllowingDescriptionSyntax는 m_fallbackToDescriptor를 true로 하는 MediaQuerySet을 만들어 parse를 부르는게 전부입니다.

parse는 넘겨받은 mediaString을 ,로 구분해서(7 line) strip하고 (9 line) CSSParser에게 parsing을 요청하는게 전부입니다.(15 line)

MediaQuery는 세가지 주요 인자를 갖는데 Restrictor( Only, Not, None)와 mediaType(String), ExpressionVector입니다.


ExpressionVector 는 MediaQueryExp를 갖는 자료형으로 Exp가 만들어지면서 유효한 expression들이 vector에 들어가게 됩니다.


이제 MediaQuery는 만들어졌으니 이전 소스코드에서 MediaQueryEvaluator::eval을 보도록 하겠습니다.

### c++; highlight: [6, 18, 19, 24]

bool MediaQueryEvaluator::eval(const MediaQuerySet* querySet, StyleResolver* styleResolver) const
{
    if (!querySet)
        return true;

    const Vector<OwnPtr<MediaQuery> >& queries = querySet->queryVector();
    if (!queries.size())
        return true; // empty query list evaluates to true

    // iterate over queries, stop if any of them eval to true (OR semantics)
    bool result = false;
    for (size_t i = 0; i < queries.size() && !result; ++i) {
        MediaQuery* query = queries[i].get();

        if (query->ignored())
            continue;

        if (mediaTypeMatch(query->mediaType())) {
            const Vector<OwnPtr<MediaQueryExp> >* exps = query->expressions();
            // iterate through expressions, stop if any of them eval to false
            // (AND semantics)
            size_t j = 0;
            for (; j < exps->size(); ++j) {
                bool exprResult = eval(exps->at(j).get());
                if (styleResolver && exps->at(j)->isViewportDependent())
                    styleResolver->addViewportDependentMediaQueryResult(exps->at(j).get(), exprResult);
                if (!exprResult)
                    break;
            }

            // assume true if we are at the end of the list,
            // otherwise assume false
            result = applyRestrictor(query->restrictor(), exps->size() == j);
        } else
            result = applyRestrictor(query->restrictor(), false);
    }

    return result;
}

6 line에서 qureySet을 vector로 변환하여 loop를 돌리면서

먼저 type이 같은지 확인합니다.(18 line)


같다면 expression들을 꺼내 (19 line), 수식을 eval()합니다.

전 예제에서 styleResolver를 넘기지 않았기 때문에 addViewportDependentMediaQueryResult는 수행하지 않습니다.

* 현재 사용중인 예제는 media type만 갖고 있습니다. 만약에 max-width:300처럼 media expression이 있다면 어떻게 될까요?

   현재 width가 1024라고 가정하면, 해당 엘리먼트는 로드하지 않을 것입니다.

   그러나, 브라우저 크기를 줄여서 width가 300이하가 되면? 해당 스타일 시트를 로드해야 합니다.

   이러한 처리를 하기 위한 것이 바로 addViewportDependentMediaQueryResult입니다.

   이 부분의 동작은 다음 글과 다다음 글을 통해 따라가 보도록 하겠습니다.


### c++; highlight: [6, 20]

static void createFunctionMap()
{
    // Create the table.
    gFunctionMap = new FunctionMap;
#define ADD_TO_FUNCTIONMAP(name, str)  \
    gFunctionMap->set(name##MediaFeature.impl(), name##MediaFeatureEval);
    CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(ADD_TO_FUNCTIONMAP);
#undef ADD_TO_FUNCTIONMAP
}

bool MediaQueryEvaluator::eval(const MediaQueryExp* expr) const
{
    if (!m_frame || !m_style)
        return m_expResult;

    if (!expr->isValid())
        return false;

    if (!gFunctionMap)
        createFunctionMap();

    // call the media feature evaluation function. Assume no prefix
    // and let trampoline functions override the prefix if prefix is
    // used
    EvalFunc func = gFunctionMap->get(expr->mediaFeature().impl());
    if (func)
        return func(expr->value(), m_style.get(), m_frame, NoPrefix);

    return false;
}

수식의 eval은 mediaFeature마다 정의된 함수를 수행하는 것입니다.

함수의 등록은 createFunctionMap안의 매크로로 이루어집니다.(20 line)


현재 등록된 mediaFeature는이 글 제일 아래를 참고하시기 바랍니다. 웹킷은 현재 CSS 스펙에 없는 media feature도 몇 가지 지원하고 있습니다.(예: device-pixel-ratio)


media feature마다 함수와 구현이 다 다르기 때문에 각각의 구현을 확인하시려면 Source/WebCore/css/MediaQueryEvaluator.cpp 를 참고하시기 바랍니다.


예제로 color를 보도록 하겠습니다. 6 line에서 보듯 'media feature명' + MediaFeatureEval()이라는 함수를 봐야 찾아야 합니다.


### c++; highlight: [3, 6]

static bool colorMediaFeatureEval(CSSValue* value, RenderStyle*, Frame* frame, MediaFeaturePrefix op)
{                                                                                      
    int bitsPerComponent = screenDepthPerComponent(frame->page()->mainFrame()->view());
    float number;                                                                      
    if (value)                                                                         
        return numberValue(value, number) && compareValue(bitsPerComponent, static_cast<int>(number), op);

    return bitsPerComponent != 0;                                                      

color 의 경우 screenDepthPerComponent라는 platform specific function으로부터 값을 꺼내오고 있습니다.해당 함수는 Source/WebCore/platform/xxx/PlatformScreenXXX.cpp에 각 포트별로 구현되어 있습니다.(XXX는 포트명)


value가 있다는 것은 현재 확인하고 있는 expression이 >, < 와 같은 비교문이 있다는 뜻(ex - color:256)입니다.

MediaFeaturePrefix는 비교하는 media feature앞에 min- 또느 max-가 붙어있는지를 전달합니다. 이 값에 따라 compareValue가 ==을 비교할지 <= 나 >=를 비교할지가 결정됩니다.





현재 등록된 media feature의 종류

### c++

#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \
    macro(color, "color") \
    macro(grid, "grid") \
    macro(monochrome, "monochrome") \
    macro(height, "height") \
    macro(hover, "hover") \
    macro(width, "width") \
    macro(orientation, "orientation") \
    macro(aspect_ratio, "aspect-ratio") \
    macro(device_aspect_ratio, "device-aspect-ratio") \
    macro(device_pixel_ratio, "-webkit-device-pixel-ratio") \
    macro(device_height, "device-height") \
    macro(device_width, "device-width") \
    macro(max_color, "max-color") \
    macro(max_aspect_ratio, "max-aspect-ratio") \
    macro(max_device_aspect_ratio, "max-device-aspect-ratio") \
    macro(max_device_pixel_ratio, "-webkit-max-device-pixel-ratio") \
    macro(max_device_height, "max-device-height") \
    macro(max_device_width, "max-device-width") \
    macro(max_height, "max-height") \
    macro(max_monochrome, "max-monochrome") \
    macro(max_width, "max-width") \
    macro(max_resolution, "max-resolution") \
    macro(min_color, "min-color") \
    macro(min_aspect_ratio, "min-aspect-ratio") \
    macro(min_device_aspect_ratio, "min-device-aspect-ratio") \
    macro(min_device_pixel_ratio, "-webkit-min-device-pixel-ratio") \
    macro(min_device_height, "min-device-height") \
    macro(min_device_width, "min-device-width") \
    macro(min_height, "min-height") \
    macro(min_monochrome, "min-monochrome") \
    macro(min_width, "min-width") \
    macro(min_resolution, "min-resolution") \
    macro(pointer, "pointer") \
    macro(resolution, "resolution") \
    macro(transform_2d, "-webkit-transform-2d") \
    macro(transform_3d, "-webkit-transform-3d") \
    macro(transition, "-webkit-transition") \
    macro(animation, "-webkit-animation") \
    macro(view_mode, "-webkit-view-mode")



저작자 표시 비영리 변경 금지
신고
Posted by 소혼

참고 자료

post comparing configure+make, cmake+make, and cmake+ninja

http://martine.github.com/ninja/manual.html


CMake 2.8.9 가 릴리즈 되었습니다.


 2.8.9의 Major change 중 하나는 Ninja가 기본으로 들어갔다는 사실입니다.

http://www.kitware.com/news/home/browse/CMake?2012_08_09&CMake+2.8.9+is+Now+Available%21



Ninja build는 빌드를 빠르게 하기 위한 툴입니다. 얼마나 빠른지는 post comparing configure+make, cmake+make, and cmake+ninja 를 참고하시면 됩니다.


현재 Ninja는 GYP와 CMake에서 지원됩니다.

CMake에서 사용하는 방법(리눅스)을 공유해보도록 하겠습니다.


1. Ninja 실행 파일 만들기

git clone git://github.com/martine/ninja.git

cd ninja

./bootstrap.py


>> ninja 파일이 생성된 것을 알 수 있습니다.

이 파일을 적절한 path에 복사합니다( /usr/local/bin )


2. cmake 2.8.9 설치

http://cmake.org/cmake/resources/software.html 에서 다운로드 받으실 수 있습니다.


3. 본인의 프로젝트에서 아래 명령 실행

mkdir bulid-dir

cd build-dir

cmake .. -G Ninja

ninja


>> 특이한 점은 make대신 ninja를 실행한다는 점입니다.

작은 규모의 프로젝트라고 해도 어마어마한 빌드속도를 경험하실 수 있습니다.


이 글이 도움이 되셨다면 아래 손가락을 눌러주세요.


저작자 표시
신고

'Open Source > cmake' 카테고리의 다른 글

CMake build with ninja  (0) 2012.09.25
[번역] CMake FAQ  (0) 2011.08.18
[CMAKE] File 다루기  (0) 2011.05.30
[cmake] 2. Hello with two files.  (0) 2011.04.12
[cmake] 목차  (0) 2011.04.12
[cmake] 2. Hello  (0) 2011.04.12
Posted by 소혼

[목차로 이동] Enlightenment Foundation Language


focus 테스트를 위해 [EFL] 3. Simple Application using Evas. 를 가지고 간단한 이벤트 테스트를 해보기로 했습니다

컴파일은 아래와 같이 하면 됩니다.
gcc -c simple simple.c `pkg-config --cflags --libs evas ecore-evas`


결론:

  - evas_object에서는 focus를 수동으로 옮겨주어야 한다.

    (elementary는 아님)


source code

#include <Evas.h>
#include <Ecore_Evas.h>
#include <stdio.h>

static void on_mouse_down(void* data, Evas* e, Evas_Object* o, void* event_info)
{
    printf("%s : %p\n", __func__, o);
}

static void on_focus_in(void* data, Evas* e, Evas_Object* o, void* event_info)
{
    printf("%s : %p\n", __func__, o);
}

static void on_focus_out(void* data, Evas* e, Evas_Object* o, void* event_info)
{
    printf("%s : %p\n", __func__, o);
}

int main()
{
    Evas* evas;
    Ecore_Evas* window;
    Evas_Object* rect2;
    Evas_Object* rect3;

    evas_init();
    ecore_init();
    ecore_evas_init();

    window = ecore_evas_new(NULL, 0, 0, 800, 600, NULL);
    evas = ecore_evas_get(window);
    ecore_evas_show(window);

    rect2 = evas_object_rectangle_add(evas);
    evas_object_color_set(rect2, 255, 0, 0,255);
    evas_object_move(rect2, 100, 100);
    evas_object_resize(rect2, 200, 200);
    evas_object_show(rect2);

    evas_object_event_callback_add(rect2, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, NULL);
    evas_object_event_callback_add(rect2, EVAS_CALLBACK_FOCUS_IN, on_focus_in, NULL);
    evas_object_event_callback_add(rect2, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, NULL);
    printf("rect2 is added : %p\n", rect2);

    rect3 = evas_object_rectangle_add(evas);
    evas_object_color_set(rect3, 0, 255, 0,255);
    evas_object_move(rect3, 400, 100);
    evas_object_resize(rect3, 200, 200);
    evas_object_show(rect3);

    evas_object_event_callback_add(rect3, EVAS_CALLBACK_MOUSE_DOWN, on_mouse_down, NULL);
    evas_object_event_callback_add(rect3, EVAS_CALLBACK_FOCUS_IN, on_focus_in, NULL);
    evas_object_event_callback_add(rect3, EVAS_CALLBACK_FOCUS_OUT, on_focus_out, NULL);
    printf("rect3 is added : %p\n", rect3);

    ecore_main_loop_begin();

    ecore_evas_shutdown();
    ecore_shutdown();
    evas_shutdown();

    return 0;
}

신고

'Open Source > EFL' 카테고리의 다른 글

[TIZEN] Tizen App store 등록하기  (0) 2013.08.01
[EFL] EFL build on ubuntu (13.04)  (1) 2013.07.24
Simple event test(mouse down/focus) using Evas  (0) 2012.09.03
[ecore] screen size 얻기  (0) 2012.08.15
[Elementary] 기본 코드  (0) 2012.08.04
[EFL] How to build EFL on Ubuntu.  (0) 2012.02.21
Posted by 소혼
TAG EFL, Evas

#include <stdio.h>
#include <ecore_x.h>

int main()
{
    ecore_x_init(0);
    Ecore_X_Screen* screen = ecore_x_default_screen_get();
    if (!screen) {
        printf("Error\n");
    }

    int w, h;
    ecore_x_screen_size_get(screen, &w, &h);
    printf("%d, %d\n", w, h);
    return 0;
}

ecore_x_init이 되어있지 않으면

ecore_x_default_screen은  crash가 난다.

신고

'Open Source > EFL' 카테고리의 다른 글

[EFL] EFL build on ubuntu (13.04)  (1) 2013.07.24
Simple event test(mouse down/focus) using Evas  (0) 2012.09.03
[ecore] screen size 얻기  (0) 2012.08.15
[Elementary] 기본 코드  (0) 2012.08.04
[EFL] How to build EFL on Ubuntu.  (0) 2012.02.21
SNAPSHOT of 2011/07/05  (0) 2011.07.06
Posted by 소혼
TAG ecore, EFL
이전버튼 1 2 3 4 5 ··· 8 이전버튼

티스토리 툴바