반응형


touch /key / etc   로 target지정   ----------> set focus  ----------> set selected   ------------> action
(touchpress)


key로만동작하는 UI에서 up down key(또는 휠)로 focus를 이동하고 나서, OK를 누르면 select가 됩니다.
어떤 컨트롤이 selected된 후에 key event를 켑쳐(?) 하겠다고 설정하면
container에서는 key event의  preview 에서 selected된 item이 있으면 ,focus 이동을 하지 않습니다.
(event bubbling이 발생합니다.)

그후 up/down은 selected된 이후에 focus이동이 아니라 




모바일에서는 플래쉬가 포기했군요.


http://www.etnews.com/news/detail.html?id=201111100110&portal=001_00001



'개발 Note > it 이야기' 카테고리의 다른 글

일탈, 디버깅 포인트  (0) 2014.09.06
C에서 C++ 그리고 framework  (0) 2014.09.02
C++를 제대로 알자!. Effective C++ , More Effective C++  (0) 2011.01.21
html5 스터디  (0) 2011.01.07
모바일에서의 GPGPU 가능성.  (0) 2011.01.03
반응형

 

Core Image Concepts


 


 

1. crop image 
2. color 수정 - white color 정정 같은 것들 수행.
3. color effect 적용  - sepia tone ,gray scale등등
4. 이미지에 Blur 나 샤픈(sharpen) 적용 
5. 이미지 합성
6. 이미지에 기하학적인 변형이나 휨 적용
7. color , 채크보더 패턴, 가우스 변환, 기타 패턴 이미지 생성.
8. 이미지나 비디오에 변환 효과 추가.
9. 비디오에 실시간 컬러 조정 제공.

Graphic system에 대한 컨셉적인 이해와 구축의 방향을 잡기에 좋은 그림이 아래의 그림입니다.
Graphics 나 Image , Video등 display와 관련 된 모든 부분은 결국 OpenGL을 이용하도록 설계되어있고, 전반적인 processing의 로드를 GPU와 분담되게 됩니다.

Figure 1-1
 gives a general idea of where Core Image fits with other graphics technologies in Mac OS X. Core Image is integrated with these technologies, allowing you to use them together to achieve a wide range of results. For example, you can use Core Image to process images created in Quartz 2D (Core Graphics) and textures created in OpenGL. You can also apply Core Image filters to video played using Core Video.

Figure 1-1  Core Image in relation to other graphics technologies


Core Image and the GPU


OpenGL은 고성능 2D and 3D 그래픽을 위한 업계 표준으로 GPU 를 사용하기 위한 인터페이스 또는 게이트웨이 같은 모듈입니다.
GPU를 이용하여 image processing을 하려면 OpenGL Shading Language를 알아야만 합니다.  
          <결국 모든 primitive 가 OpenGL 을 사용하게 되면 image processing 역시 GPU의 로드로 넘길 수 있다는 의미로 해석되는 군요.>


현재 대부분의 시스템들은 2D primitive drawing은 CPU를 통한 buffer에 processing 하는 방식과 GPU를 사용하는 방식등 , 혼재되어있는 시스템들이 많다.
이렇게 단일 Graphic module을 사용하지 않아 ,Buffer에 그린 image를 GPU가속을 받기 위해 OpenGL texture로 변환한다거나, 또는 double buffering을 위해 따로 메모리를 잡고 하는 , 중복적인 기능들이 필요하게 되고, GPU 의 도움을 받지 않고 image filtering을 한다거나 변환을 행하는 경우는  CPU에 더더욱 큰 부하를 주게 됩니다.

그런 의미에서 iOS의 그래픽 시스템은 보고 배울만한 교과서 같은 시스템 처럼 느껴집니다.

 Graphics module 과 정책에 대해서는 Quartz를 좀 살펴 봐야 하는데, 이는 따로 정리할 필요하 있을것 같습니다.

 

Filter Clients and Filter Creators


Core Image 는 필터 사용자와 필터 제작자 이렇게 두가지 형태의 개발자를 위해 설계되었습니다.( 모두를 위해서라고 표현해야 하나?)

filter category 는 이펙트 타입 즉, blur, distortion, generator 등등 과 정지 이미지, 비디오 사각형이 아닌 픽셀 을 위한 것들이 명시됩니다.




아래의 대표적인 필터의 컴포넌트를 자세히 들여다 본것입니다.

outputImage 메소드는  이미지를 만들어는 것이 가능하도록 계산 결과들을 모으고 저장한다. 그러나 실제로 Core Image를 이미지 프로세싱 하지 않는다.
Core Image는 lazy evaluation을 사용하기 때문입니다.
                         < 어떤 작업을 되도록 늦추고 늦춰서 꼭 필요해지는 최종 순간에 처리하는 것을 의미합니다..>

다른게 표현하면, processing된 pixel을 최종 타겟에 실제로 칠해야 하는 시점이 오기 전까지는 Core Image가 image processing하는 일은 없다고 할수 있겠군요.

outputImage 메소드는 Core Image가 필요로 하는 계산 값들을 모으거나 , CIImage에 계산 값들을 저장하는 것 밖에 없다. 실제 이미지는 가 만들어지는 것은  명시적으로 image drawing 메소드가 불렸을  때 뿐이다.  (drawImage:atPoint:fromRect 나 drawImage:inRect:fromRect 같은 메소드)

Figure 1-2  The components of a typical filter
The components of a typical filter

Core Image stores the calculations until your application issues a command to draw the image. At that time, Core Image calculates the results. Lazy evaluation is one of the practices that makes Core Image fast and efficient. At rendering time, Core Image can see if more than one filter needs to be applied to an image. If so, it can concatenate multiple “recipes” into one operation, which means each pixel is processed once rather than many times. Figure 1-3 illustrates how lazy evaluation can make image processing more efficient for multiple operations. The final image is a scaled-down version of the original. For the case of a large image, applying color adjustment before scaling down the image requires more processing power than scaling down the image and then applying color adjustment. Because Core Image waits until the last possible moment to apply filters, it can perform these operations in reverse order, which is more efficient.

Figure 1-3  A work flow that can benefit from lazy evaluation

For the filter creator, the most exciting component of a filter is the kernel, which is at the heart of every filter. The kernel specifies the calculations that are performed on each source image pixel. Kernel calculations can be very simple or complex. A very simple kernel for a “do nothing” filter could simply return the source pixel:

destination pixel = source pixel

Filter creators use a variant of OpenGL Shading Language (glslang) to specify per-pixel calculations. (See Core Image Kernel Language Reference.) The kernel is opaque to a filter client. A filter can actually use several kernel routines, passing the output of one to the input of another. For instructions on how to write a custom filter, see “Creating a Custom Filter.”

Filter creators can make their custom filters available to any application by packaging them as a plug-in, or image unit, using the architecture specified by the NSBundle class. An image unit can contain more than one filter, as shown in Figure 1-4. For example, you could write a set of filters that perform different kinds of edge detection and package them as a single image unit. Filter clients can use the Core Image API to load the image unit and to obtain a list of the filters contained in that image unit. See “Loading Image Units” for basic information. See Image Unit Tutorial for in-depth examples and detailed information on writing filters and packaging them as standalone image units.

Figure 1-4  An image unit contains packaging information along with one or more filter definitions

The Processing Path

Figure 1-5 shows the pixel processing path for a filter that operates on two sources images. Source images are always specified as CIImage objects. Core Image provides a variety of ways to get image data. You can supply a URL to an image, read raw image data (using the NSData class), or convert a Quartz 2D image (CGContextRef), an OpenGL texture, or a Core Video image buffer (CVImageBufferRef) to a CIImage object.

Note that the actual number of input images, and whether or not the filter requires an input image, depends on the filter. Filters are very flexible—a filter can:

  • Work without an input image. Some filters generate an image based on input parameters that aren’t images. (For example, see the CICheckerboardGenerator and CIConstantColorGeneratorfilters in Core Image Filter Reference.)

  • Require one image. (For example, see the CIColorPosterize and CICMYKHalftone filters in Core Image Filter Reference.)

  • Require two or more images. Filters that composite images or use the values in one image to control how the pixels in another image are processed typically require two or more images. One input image can act as a shading image, an image mask, a background image, or provide a source of lookup values that control some aspect of how the other image is processed. (For example, see theCIShadedMaterial filter in Core Image Filter Reference.)

When you process an image, it is your responsibility to create a CIImage object that contains the appropriate input data.

Figure 1-5  The pixel processing path

Pixels from each source image are fetched by a CISampler object, or simply a sampler. As its name suggests, a sampler retrieves samples of an image and provides them to a kernel. A filter creator provides a sampler for each source image. Filter clients don’t need to know anything about samplers.

A sampler defines:

  • A coordinate transform, which can be the identity transform if no transformation is needed.

  • An interpolation mode, which can be nearest neighbor sampling or bilinear interpolation (which is the default).

  • A wrapping mode that specifies how to produce pixels when the sampled area is outside of the source image—either to use transparent black or clamp to the extent.

The filter creator defines the per-pixel image processing calculations in the kernel, but Core Image handles the actual implementation of those calculations. Core Image determines whether the calculations are performed using the GPU or the CPU. Core Image implements hardware rasterization through OpenGL. It implements software rasterization through an emulation environment specifically tuned for evaluating fragment programs with nonprojective texture lookups over large quadrilaterals (quads).

Although the pixel processing path is from source image to destination, the calculation path that Core Image uses begins at the destination and works its way back to the source pixels, as shown in Figure 1-6. This backward calculation might seem unwieldy, but it actually minimizes the number of pixels used in any calculation. The alternative, which Core Image does not use, is the brute force method of processing all source pixels, then later deciding what’s needed for the destination. Let’s take a closer look at Figure 1-6.

Figure 1-6  The Core Image calculation path

Assume that the filter in Figure 1-6 performs some kind of compositing operation, such as source-over compositing. The filter client wants to overlap the two images, so that only a small portion of each image is composited to achieve the result shown at the left side of the figure. By looking ahead to what the destination ought to be, Core Image can determine which data from the source images affect the final image and then restrict calculations only to those source pixels. As a result, the samplers fetch samples only from shaded areas in the source images shown in Figure 1-6.

Note the box in the figure that’s labeled domain of definition. The domain of definition is simply a way to further restrict calculations. It is an area outside of which all pixels are transparent (that is, the alpha component is equal to 0). In this example, the domain of definition coincides exactly with the destination image. Core Image lets you supply a CIFilterShape object to define this area. TheCIFilterShape class provides a number of methods that can define rectangular shapes, transform shapes, and perform inset, union, and intersection operations on shapes. For example, if you define a filter shape using a rectangle that is smaller than the shaded area shown in Figure 1-6, then Core Image uses that information to further restrict the source pixels used in the calculation.

Core Image promotes efficient processing in other ways. It performs intelligent caching and compiler optimizations that make it well suited for such tasks as real-time video control. It caches intermediate results for any data set that is evaluated repeatedly. Core Image evicts data in least-recently-used order whenever adding a new image would cause the cache to grow too large, which means objects that are reused frequently remain in the cache, while those used once in a while might be moved in and out of the cache as needed. Your application benefits from Core Image caching without needing to know the details of how caching is implemented. However, you get the best performance by reusing objects (images, contexts, and so forth) whenever you can.

Core Image also gets great performance by using traditional compilation techniques at the kernel and pass levels. The method Core Image uses to allocate registers minimizes the number of temporary registers (per kernel) and temporary pixel buffers (per filter graph). The compiler performs CSE and peephole optimization and automatically distinguishes between reading data-dependent textures, which are based on previous calculations, and those that are not data-dependent. Again, you don’t need to concern yourself with the details of the compilation techniques. The important point is that Core Image is hardware savvy; it uses the power of the GPU whenever it can, and it does so in smart ways.

Coordinate Spaces

Core Image performs operations in a device-independent working space, similar in concept to what’s shown in Figure 1-7. The Core Image working space is, in theory, infinite in extent. A point in working space is represented by a coordinate pair (xy), where x represents the location along the horizontal axis and y represents the location along the vertical axis. Coordinates are floating-point values. By default, the origin is point (0,0).

When Core Image reads images, it translates the pixel locations into device-independent working space coordinates. When it is time to display a processed image, Core Image translates the working space coordinates to the appropriate coordinates for the destination, such as a display.

Figure 1-7  Core Image performs image operations in a device-independent working space

When you write your own filters, you need to be familiar with two coordinate spaces—the destination coordinate space and the sampler space. The destination coordinate space represents the image you are rendering to. The sampler space represents what you are texturing from (another image, a lookup table, and so on). You obtain the current location in destination space using the destCoord function whereas the samplerCoord function provides the current location in sample space. (See Core Image Kernel Language Reference.)

Keep in mind that if your source data is tiled, the sampler coordinates have an offset (dx/dy). If your sample coordinates have an offset, it may be necessary for you to convert the destination location to the sampler location using the function samplerTransform.

The Region of Interest

Although not explicitly labeled in Figure 1-6, the shaded area in each of the source images is the region of interest for samplers depicted in the figure. The region of interest, or ROI, defines the area in the source from which a sampler takes pixel information to provide to the kernel for processing. If you are a filter client, you don’t need to concern yourself with the ROI. But if you are a filter creator, you’ll want to understand the relationship between the region of interest and the domain of definition.

Recall that the domain of definition describes the bounding shape of a filter. In theory, this shape can be without bounds. Consider, for example, a filter that creates a repeating pattern that could extend to infinity.

The ROI and the domain of definition can relate to each other in the following ways:

  • They coincide exactly—there is a 1:1 mapping between source and destination. For example, a hue filter processes a pixel from the working space coordinate (r,s) in the ROI to produce a pixel at the working space coordinate (r,s) in the domain of definition.

  • They are dependent on each other, but modulated in some way. Some of the most interesting filters—blur and distortion, for example—use many source pixels in the calculation of one destination pixel. For example, a distortion filter might use a pixel (r,s) and its neighbors from the working coordinate space in the ROI to produce a single pixel (r,s) in the domain of definition.

  • The domain of definition is calculated from values in a lookup table that are provided by the sampler. The location of values in the map or table are unrelated to the working space coordinates in the source image and the destination. A value located at (r,s) in a shading image does not need to be the value that produces a pixel at the working space coordinate (r,s) in the domain of definition. Many filters use values provided in a shading image or lookup table in combination with an image source. For example, a color ramp or a table that approximates a function, such as the arcsin function, provides values that are unrelated to the notion of working coordinates.

Unless otherwise instructed, Core Image assumes that the ROI and the domain of definition coincide. If you write a filter for which this assumption doesn’t hold, you need to provide Core Image with a routine that calculates the ROI for a particular sampler.

See “Supplying an ROI Function” for more information.

Executable and Nonexecutable Filters

You can categorize custom Core Image filters on the basis of whether or not they require an auxiliary binary executable to be loaded into the address space of the client application. As you use the Core Image API, you’ll notice that these are simply referred to as executable and nonexecutable. Filter creators can choose to write either kind of filter. Filter clients can choose to use only nonexecutable or to use both kinds of filters.

Security is the primary motivation for distinguishing CPU executable and CPU nonexecutable filters. Nonexecutable filters consist only of a Core Image kernel program to describe the filter operation. In contrast, an executable filter also contains machine code that runs on the CPU. Core Image kernel programs run within a restricted environment and cannot pose as a virus, Trojan horse, or other security threat, whereas arbitrary code that runs on the CPU can.

Nonexecutable filters have special requirements, one of which is that nonexecutable filters must be packaged as part of an image unit. Filter creators can read “Writing Nonexecutable Filters” for more information. Filter clients can find information on loading each kind of filter in “Loading Image Units.”

Color Components and Premultiplied Alpha

Premultiplied alpha is a term used to describe a source color, the components of which have already been multiplied by an alpha value. Premultiplying speeds up the rendering of an image by eliminating the need to perform a multiplication operation for each color component. For example, in an RGB color space, rendering an image with premultiplied alpha eliminates three multiplication operations (red times alpha, green times alpha, and blue times alpha) for each pixel in the image.

Filter creators must supply Core Image with color components that are premultiplied by the alpha value. Otherwise, the filter behaves as if the alpha value for a color component is 1.0. Making sure color components are premultiplied is important for filters that manipulate color.

By default, Core Image assumes that processing nodes are 128 bits-per-pixel, linear light, premultiplied RGBA floating-point values that use the GenericRGB color space. You can specify a different working color space by providing a Quartz 2D CGColorSpace object. Note that the working color space must be RGB-based. If you have YUV data as input (or other data that is not RGB-based), you can use ColorSync functions to convert to the working color space. (See Quartz 2D Programming Guide for information on creating and using CGColorspace objects.)

With 8-bit YUV 4:2:2 sources, Core Image can process 240 HD layers per gigabyte. Eight-bit YUV is the native color format for video source such as DV, MPEG, uncompressed D1, and JPEG. You need to convert YUV color spaces to an RGB color space for Core Image.



펌 [http://developer.apple.com읽으면서 기억에 남는 내용을 정리 했습니다.
반응형



가끔 개인적으로  stdafx.h 는 골치 아프게 할때가 있습니다..

테스트 코드를 작성해서 시험해보거나, Code generation 툴을 이용해서 만들어진 코드에 작업하는 경우, 그리고 작성된 코드를 visual studio가 아닌,
개발환경( gcc , armcc 등등 ) 에서 cross compile 해야 하는경우 등이 대표적인 예입니다.


visual studio 에서 Win32 Project를 만들었을 경우,  stdafx.h 를 없애기 위한 절차는 다음과 같습니다.

1. 
프로젝트 프라퍼티( Property) -> C/C++ -> Precompiled Headers
: Create/Use Precompiled Header :Not Using Precompiled Headers 로 변경

2. 각 소스파일에서 include "stdafx.h" 를 없앤다.


3. 이렇게 변경을 하고 나면, 아마 이런 에러가 날것입니다.
unresolved external symbol _WinMain@16 referenced in function ___tmainCRTStartup 

이 에러는 WinMain이 없다는 예기인데요.

3. 위와 같은 에러가 발생하면, Main이 들어있는 소스 파일을 확인해보자.

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)


Visual studio 에서 사용되는 CRT library가 _tWinMain을 호출하도록 되어있습니다.
그런데 우리가 Precompiled header를 없앴기 때문에, 이제 WinMain을 요구하는 것이죠.
그래서 위의 _tWinMain을 WinMain으로 변경하면 됩니다.
이때 주의 사항은 3번째 파라미터 인 LPSTR    lpCmdLine 입니다.
tWinMain에서는 LPSTR로 되어있어서 그냥 이름만 바꾸면 안되고, parameter 타입도 확인하셔야 합니다.

[WinMain 의 prototype]
 

int WINAPI WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR    lpCmdLine,
                     int       nCmdShow) 



여기까지 하고 나면 빌드 성공!!!!!

즐거운 프로그래밍 생활 하세요!


반응형

에플 개발 사이트에서 core animation 관련 내용을 발최 필요한 부분을 번역하였습니다.


What Is Core Animation?

Core Animation is a collection of Objective-C classes for graphics rendering, projection, and animation. It provides fluid animations using advanced compositing effects while retaining a hierarchical layer abstraction that is familiar to developers using the Application Kit and Cocoa Touch view architectures.

Dynamic, animated user interfaces are hard to create, but Core Animation makes creating these interfaces easier by providing:

- High performance compositing with a simple approachable programming model.
- A familiar view-like abstraction that allows you to create complex user interfaces using a hierarchy of layer objects.
- A lightweight data structure. You can display and animate hundreds of layers simultaneously.
- An abstract animation interface that allows animations to run on a separate thread, independent of your application's run loop. Once an animation is configured and starts, Core Animation assumes full responsibility for running it at frame rate.
- Improved application performance. Applications need only redraw content when it changes. Minimal application interaction is required for resizing and providing layout services layers. Core Animation also eliminates application code that runs at the animation frame-rate.
- A flexible layout manager model, including a manager that allows the position and size of a layer to be set relative to attributes of sibling layers.

Using Core Animation, developers can create dynamic user interfaces for their applications without having to use low-level graphics APIs such as OpenGL to get respectable animation performance.


Core Animation Classes 


Core Animation classes can be grouped into several categories:
  • Layer classes that provide content for display

  • Animation and timing classes

  • Layout and constraint classes

  • A transaction class that groups multiple layer changes into an atomic update

기본 Core Animation class들은 Quartz Core framework.에 포함되어있고, 추가적인 layer class들은 다른 framework에 포함될 수 있다.  Figure 1 " Core Animation Class" class 계층도를 이다.

Figure 1 Core Animation class hierarchy
 



Layer Classes

Layer class는 Core Animation의 기반이며 NSView나 UIView를 이용하는 개발자들에게 친숙한 추상화(abstraction)를 제공한다. - abstraction 을 class 추상화 로 생각하는 것이 좋을것 같음.
CALayer는 모든 Core Animaton layer들의 부모 클래스로서 기본 Layer의 기능을 제공한다.
 

View 클래스의 인스턴스(객체) 는  레이어 트리에서 제공하는 것처럼 레이어 계층구조를 만든다.

 - CALayer 인스턴스는 하나의 부모 레이어(Super layer)와 자식 레이어(Sub Layer)들에 대한 콜랙션(collection- 자료구조)을 갖고 있다. 

레이어들은 뷰(View)와 비슷하게 뒤에서부터 앞으로 그려지고 부모 레이어(Super Layer)를 로컬(local) 좌표계를 생성하는 것과 같이 상대적 위치나 형태를 취하게 된다. 
그러나, 레이어들은  회전(rotate),비틀림(skew), 크기변환( scale) , 투영(project)와 같은 변환 행렬을 레이어 컨텐츠(content)에 적용하는 것과 같은 좀더 복잡한 표현들을 제공한다. 

"Layer Geometry and Transforms" 는 레이어 도형(Geometry) 와 변환(transform)에 대해 좀더 자세하게 다루고 있다.

 CALayer는 Application Kit과 Cocoa Touch view class들로 분기하기에, 컨텐츠를 표현하기 위해 CALayer에서 파생(subclass)될 필요가 없다. 컨텐츠는 CALayer 인스턴스에 의해 아래와 같은 방법으로 출력된다.

  • Core Graphics 의 Image Representation 으로 직접 또는 델리게이션(delegation)을 통해서 레이어의 컨텐츠 속성(property) 세팅.
  • Core Graphics Image Context를 통해 직접 그리는 델리게이트( delegate)를 제공.
  • 여러가지 비쥬얼 스타일 속성 설정 제공
    • 모든레이어에 공통적으로 가지고 있는 속성으로 예를 들면,
    • 배경색( background color), 투명도(opacity), 마스킹(masking)등이다. 
      - Mac OS X 어플리케이션 역시 비쥬얼 속성( property)을 접근할 수 있으며 Core Image filter를 사용할수 있다.
  • CALayer 파생(상속, subclassing) 이나 좀더 켑슐화된 방법의 높은 수준의 기술을 통한 구현.



“Providing Layer Content” describes the available techniques for providing the content for a layer. The visual style properties and the order in which they are applied to the content of a layer is discussed in “Layer Style Properties.”

In addition to the CALayer class, the Core Animation class collection provides additional classes that allow applications to display other types of content. The available classes differ slightly between Mac OS X and iOS. The following classes are available on both Mac OS X and iOS:

  • CAScrollLayer class is a subclass of CALayer that simplifies displaying a portion of a layer. The extent of the scrollable area of a CAScrollLayer object is defined by the layout of its sublayers. CAScrollLayer does not provide keyboard or mouse event-handling, nor does it provide visible scrollers.

  • CATextLayer is a convenience class that creates a layer's content from a string or attributed string.

  • CATiledLayer allows the display of large and complex images in incremental stages.

Mac OS X provides these additional classes:

  • CAOpenGLLayer provides an OpenGL rendering environment. You must subclass this class to provide content using OpenGL. The content can be static or can be updated over time.

  • QCCompositionLayer (provided by the Quartz Composer framework) animates a Quartz Composer composition as its content.

  • QTMovieLayer and QTCaptureLayer (provided by the QTKit framework) provides playback of QuickTime movies and live video.

iOS adds the following class:

  • CAEAGLLayer provides an OpenGLES rendering environment.

The CALayer class introduces the concept of a key-value coding compliant container class–that is, a class that can store arbitrary values, using key-value coding compliant methods, without having to create a subclass. CALayer also extends the NSKeyValueCoding informal protocol, adding support for default key values and automatic object wrapping for the additional structure types (CGPointCGSizeCGRectCGAffineTransform and CATransform3D) and provides access to many of the fields of those structures by key path.

CALayer also manages the animations and actions that are associated with a layer. Layers receive action triggers in response to layers being inserted and removed from the layer tree, modifications being made to layer properties, or explicit developer requests. These actions typically result in an animation occurring. See “Animation” and “Layer Actions” for more information.

Animation and Timing Classes


한 레이어의 비쥬얼 프라퍼티들중 많은 것들이 Implicitly(자동,무조건적인) 에니메이션 가능하다. 에니메이션이 가능한 프라퍼티의 값을 간단히 변경하는 것으로 레이어는 자동으로 현재 값에서 새로 세팅된 값으로 에니메이션 한다. 예로 레이어의 숨김(hidden) 프라퍼티를 YES로 설정하면 레이어는 천천히 사라진다. 대부분의 에니메이션이 가능한 프라퍼티들은 사용자가 조작하거나 변경할수 있도록 기본적인 에니메이션을 가지고 있다. 에니메이션 가능한 프라퍼티의 전체 목록은 "Animatable Properties" 에 있다.



에니메이션 프라퍼티들은 explicit 에니메이션으로 사용할 수 있다. Core Animation 의 animation class 로 인스턴스를 만들고 비쥬얼 이펙트를 설정하여 explicit 에니메이션을 만들 수 있다.
explicit animation은 Layer에서 프라퍼티 값을 변경하지 않고, display 단에서 간단한 에니메이션을 한다. 
(
An explicit animation doesn’t change the value of the property in the layer, it simply animates it in the display.


제가 알아본 결과 : 
explicit animation 은 layer에 사용자가 원하는 에니메이션을 세팅 할 수 있는 기능으로,animation 되는 동안 layer의 property는 변경되지 않는 다고 합니다.
 

 


Core Animation provides animation classes that can animate the entire contents of a layer or selected attributes using both basic animation and key-frame animation. All Core Animation's animation classes descend from the abstract class 
CAAnimationCAAnimation adopts the CAMediaTiming protocol which provides the simple duration, speed, and repeat count for an animation.CAAnimation also adopts the CAAction protocol. This protocol provides a standardized means for starting an animation in response to an action triggered by a layer.

The animation classes also define a timing function that describes the pacing of the animation as a simple Bezier curve. For example, a linear timing function specifies that the animation's pace is even across its duration, while an ease-out timing function causes an animation to slow down as it nears its duration.

Core Animation provides a number of additional abstract and concrete animation classes:

  • CATransition provides a transition effect that affects the entire layer's content. It fades, pushes, or reveals layer content when animating. The stock transition effects can be extended by providing your own custom Core Image filters.

  • CAAnimationGroup allows an array of animation objects to be grouped together and run concurrently.

  • CAPropertyAnimation is an abstract subclass that provides support for animating a layer property specified by a key path.

  • CABasicAnimation provides simple interpolation for a layer property.

  • CAKeyframeAnimation provides support for key frame animation. You specify the key path of the layer property to be animated, an array of values that represent the value at each stage of the animation, as well as arrays of key frame times and timing functions. As the animation runs, each value is set in turn using the specified interpolation.

These animation classes are used by both Core Animation and Cocoa Animation proxies. “Animation” describes the classes as they pertain to Core Animation, Animation Types and Timing Programming Guide contains a more in-depth exploration of their capabilities.

Layout Manager Classes

Application Kit view classes provide the classic "struts and springs" model of positioning layers relative to their superlayer. While layers support this model, Core Animation on Mac OS X also provides a more flexible layout manager mechanism that allows developers to write their own layout managers.

Core Animation’s CAConstraint class is a layout manager that arranges sublayers using a set of constraints that you specify. Each constraint (encapsulated by instances of the CAConstraintclass) describes the relationship of one geometric attribute of a layer (the left, right, top, or bottom edge or the horizontal or vertical center) in relation to a geometric attribute of one of its sibling layers or its superlayer.

Layout managers in general, and the constraint layout manager are discussed in “Laying Out Core Animation Layers”

Transaction Management Classes

Every modification to an animatable property of a layer must be part of a transaction. CATransaction is the Core Animation class responsible for batching multiple animation operations into atomic updates to the display. Nested transactions are supported.


Core Animation 은 implicit transaction 와 explicit transaction  2가지 타입의 트랜젝션(transaction)을 제공한다. 
Implicit transaction은 쓰레드(thread)에서 active transaction 없이 레이어의 에니메이션가능한 속성이 수정되면 자동으로 생성된다.  그리고 쓰레드 루프(run-loop)에서 다음 수행(iterate)될때 자동으로 수행된다. 
Explicit transaction 은 어플리케이션이 레이어를 수정하기 전에 CATransaction class의 begin message 를 보내고  commit message를 할때 수행된다. 

 

Transaction management is discussed in “Transactions.”




Core Animation Rendering Architecture

Core Animation의 Layer와 Cocoa view사이에 명백하게 비슷한 점들이 있는 동시에 가장 큰 념적인 차이는 스크린에 직접 그리지는 않는다.

NSView와 UIView는 MVC(model-view-controller)디자인 패턴에서 뷰 오브젝트(view object)에 해당하고, Core Animation 의 Layer는 모델 오브젝트(model object)에 해당한다. Layer는 형체 정보(geometry), 타이밍(timing) 과 visual property, 그들이 제공하는 표시된 컨텐츠(content)를 켑슐화(encapsulate)하고 있으나, 실제 보여지는 것이 Layer의  기능은 아니다.


각의 레이어 트리에는 2개의 대응되는 트리가 있다. Presentation tree와 Render Tree이다.
그림1은 Mac OS X에서의 유효한 Core Animation layer class를 이용한 Layer트리의 예를 보여준다.
 

Figure 1  Core Animation Rendering Architecture



레이어 트리(Layer tree)는 각 레이어의 객체 모델 값(Value)들을 포함하고 있다. 이 값들은 레이어 프라퍼티(Layer property)에 설정한 값이다.

Presentation Tree 는 현재 에니메이션 위치의 값들을 가지고있다.
한 예로 새로운 값을 Layer의 backgroundColor에 설정하면, Layer tree의 값은 즉시 바뀐다. 그러나 Presentation tree에 해당하는 Layer의 backgroundColor 값은 presentation tree의 layer들이 화면에 반영되는 시점에 업데이트된다.
(interpolate 되는 시점이 rendering 직전이라고 이해하면 될것 같다).

레이어를 렌더링 할때 렌더 트리는 presentation-tree의 값을 사용한다. 렌더 트리는 어플리케이션의 엑티비티와는 독립적으로 구성가능하도록 하는 역할을 맡고있다.
렌더링이 어플리케이션 실행 루프에서 최소한의 영향을 주도록 분리된 프로세스나 스레드에서 실행된다.

프로세스내에서 animation이 수행되는 동안 Presentation Layer에 해당하는 CALayer의 인스턴스에 접근할 수 있다.
이는 현재 에니매이션되고 있는 상태를 가지고 새로운 에니메이션을 시키고자할때 매우 유용하다. 






Layer Geometry and Transforms

This chapter describes the components of a layer’s geometry, how they interrelate, and how transform matrices can produce complex visual effects.

Layer Coordinate System

The coordinate system for layers differs depending on the current platform. In iOS, the default coordinate system origin is in the top-left corner of the layer and positive values extend down and to the right of that origin point. In Mac OS X, the default coordinate system origin is in the lower-left corner of the layer and positive values extend up and to the right of that point. All coordinate values are specified as floating-point numbers. And any layers you create on a given platform use the default coordinate system associated with that platform.

Every layer object defines and maintains its own coordinate system, and all content in a layer is positioned relative to this coordinate system. This is true both for the layer contents itself and for any sublayers. Because each layer defines its own coordinate system, the CALayer class provides methods to convert point, rectangle and size values from the coordinate system of one layer to another.

Some layer-related properties measure their values using the unit coordinate space. The unit coordinate space is a way of specifying values relative to the bounds of the layer but without tying that property to the exact bounds values. A given x or y coordinate in the unit coordinate space is always in the range of 0.0 to 1.0. Specifying a value of 0.0 along the x axis yields a point on the left edge of the layer while specifying a value of 1.0 yields a point on the right edge of the layer. (For y values, which value is along the top edge and which value is along the bottom edge depends on the underlying platform and follows the same rules as previously described.) A point of (0.5, 0.5) yields a point in the exact center of the layer.

Specifying a Layer’s Geometry

While layers and the layer-tree are analogous to views and view hierarchies in many ways, a layer's geometry is specified in a different, and often simpler, manner. All of a layer’s geometric properties, including the layer’s transform matrices, can be implicitly and explicitly animated.

Figure 1 shows the properties used to specify a layer's geometry in context.

Figure 1  CALayer geometry properties


The position property is a CGPoint that specifies the position of the layer relative to its superlayer, and is expressed in the superlayer's coordinate system.

The bounds property is a CGRect that provides the size of the layer (bounds.size) and the origin (bounds.origin). The bounds origin is used as the origin of the graphics context when you override a layer's drawing methods.

Layers have an implicit frame that is a function of the positionboundsanchorPoint, and transform properties. Setting a new frame rectangle changes the layer's position and boundsproperties appropriately, but the frame itself is not stored. When a new frame rectangle is specified the bounds origin is undisturbed, while the bounds size is set to the size of the frame. The layer's position is set to the proper location relative to the anchor point. When you get the frame property value, it is calculated relative to the positionbounds, and anchorPoint properties.

The anchorPoint property is a CGPoint that specifies a location within the bounds of a layer that corresponds with the position coordinate. The anchor point specifies how the bounds are positioned relative to the position property, as well as serving as the point that transforms are applied around. It is expressed in the unit coordinate system-the (0.0,0.0) value is located closest to the layer’s origin and (1.0,1.0) is located in the opposite corner. Applying a transform to the layer’s parent (if one exists) can alter the anchorPoint orientation, depending on the parent’s coordinate system on the y-axis.

When you specify the frame of a layer, position is set relative to the anchor point. When you specify the position of the layer, bounds is set relative to the anchor point.

Figure 2 shows three example values for an anchor point.

Figure 2  Three anchorPoint values


The default value for anchorPoint is (0.5,0.5) which corresponds to the center of the layer's bounds (shown as point A in Figure 2.) Point B shows the position of an anchor point set to (0.0,0.5). Finally, point C (1.0,0.0) causes specifies that the layer’s position is set to the bottom right corner of the frame. This diagram is specific to layers in Mac OS X. In iOS, layers use a different default coordinate system, where (0.0,0.0) is in the top-left corner and (1.0,1.0) is in the lower-right.

The relationship of the frameboundsposition, and anchorPoint properties is shown in Figure 3.

Figure 3  Layer Origin of (0.5,0.5)


In this example the anchorPoint is set to the default value of (0.5,0.5), which corresponds to the center of the layer. The position of the layer is set to (100.0,100.0), and the bounds is set to the rectangle (0.0, 0.0, 120.0, 80.0). This causes the frame property to be calculated as (40.0, 60.0, 120.0, 80.0).

If you created a new layer, and set only the layer’s frame property to (40.0, 60.0, 120.0, 80.0), the position property would be automatically set to (100.0,100.0), and the bounds property to (0.0, 0.0, 120.0, 80.0).

Figure 4 shows a layer with the same frame rectangle as the layer in Figure 3. However, in this case the anchorPoint of the layer is set to (0.0,0.0), which corresponds with the bottom left corner of the layer.

Figure 4  Layer Origin of (0.0,0.0)


With the frame set to (40.0, 60.0, 120.0, 80.0), the value of the bounds property is the same, but the value of the position property has changed.

Another aspect of layer geometry that differs from Cocoa views is that you can specify a radius that is used to round the corners of the layer. The cornerRadius property specifies a radius the layer uses when drawing content, clipping sublayers, and drawing the border and shadow.

The zPosition property specifies the z-axis component of the layer's position. The zPosition is intended to be used to set the visual position of the layer relative to its sibling layers. It should not be used to specify the order of layer siblings, instead reorder the layer in the sublayer array.

Transforming a Layer’s Geometry

Once established, you can transform a layer's geometry using matrix transformations. The CATransform3D data structure defines a homogenous three-dimensional transform (a 4 by 4 matrix ofCGFloat values) that is used to rotate, scale, offset, skew, and apply perspective transformations to a layer.

Two layer properties specify transform matrices: transform and sublayerTransform. The matrix specified by the transform property is applied to the layer and its sublayers relative to the layer's anchorPointFigure 3 shows how rotation and scaling transforms affect a layer when using an anchorPoint of (0.5,0.5), the default value. Figure 4 shows how the same transform matrices affect a layer when an anchorPoint of (0.0,0.0). The matrix specified by the sublayerTransform property is applied only to the layer’s sublayers, rather than to the layer itself.

You create and modify CATransform3D data structures in one of the following ways:

  • using the CATransform3D functions

  • modifying the data structure members directly

  • using key-value coding and key paths.

The constant CATransform3DIdentity is the identity matrix, a matrix that has no scale, rotation, skewing, or perspective applied. Applying the identity matrix to a layer causes it to be displayed with its default geometry.

Transform Functions

The transform functions available in Core Animation operate on matrices. You can use these functions (shown in Table 1) to construct a matrix that you later apply to a layer or its sublayers by modifying the transform or sublayerTransform properties respectively. The transform functions either operate on, or return, a CATransform3D data structure. This enables you to construct simple or complex transforms that you can readily reuse.

Table 1  CATransform3D transform functions for translation, rotation, and scaling

Function

Use

CATransform3DMakeTranslation

Returns a transform that translates by '(tx, ty, tz)'. t' = [1 0 0 0; 0 1 0 0; 0 0 1 0; tx ty tz 1].

CATransform3DTranslate

Translate 't' by '(tx, ty, tz)' and return the result: * t' = translate(tx, ty, tz) * t.

CATransform3DMakeScale

Returns a transform that scales by `(sx, sy, sz)': * t' = [sx 0 0 0; 0 sy 0 0; 0 0 sz 0; 0 0 0 1].

CATransform3DScale

Scale 't' by '(sx, sy, sz)' and return the result: * t' = scale(sx, sy, sz) * t.

CATransform3DMakeRotation

Returns a transform that rotates by 'angle' radians about the vector '(x, y, z)'. If the vector has length zero the identity transform is returned.

CATransform3DRotate

Rotate 't' by 'angle' radians about the vector '(x, y, z)' and return the result. t' = rotation(angle, x, y, z) * t.

The angle of rotation is specified in radians rather than degrees. The following functions allow you to convert between radians and degrees.

CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180 / M_PI;};

Core Animation provides a transform function that inverts a matrix, CATransform3DInvert. Inversion is generally used to provide reverse transformation of points within transformed objects. Inversion can be useful when you need to recover a value that has been transformed by a matrix: invert the matrix, and multiply the value by the inverted matrix, and the result is the original value.

Functions are also provided that allow you to convert a CATransform3D matrix to a CGAffineTransform matrix, if the CATransform3D matrix can be expressed as such.

Table 2  CATransform3D transform functions for CGAffineTransform conversion

Function

Use

CATransform3DMakeAffineTransform

Returns a CATransform3D with the same effect as the passed affine transform.

CATransform3DIsAffine

Returns YES if the passed CATransform3D can be exactly represented an affine transform.

CATransform3DGetAffineTransform

Returns the affine transform represented by the passed CATransform3D.

Functions are provided for comparing transform matrices for equality with the identity matrix, or another transform matrix.

Table 3  CATransform3D transform functions for testing equality

Function

Use

CATransform3DIsIdentity

Returns YES if the transform is the identity transform.

CATransform3DEqualToTransform

Returns YES if the two transforms are exactly equal..

Modifying the Transform Data Structure

You can modify the value of any of the CATransform3D data structure members as you would any other data structure. Listing 1 contains the definition of the CATransform3D data structure, the structure members are shown in their corresponding matrix positions.

Listing 1  CATransform3D structure

struct CATransform3D

{


  CGFloat m11, m12, m13, m14;

  CGFloat m21, m22, m23, m24;

  CGFloat m31, m32, m33, m34;

  CGFloat m41, m42, m43, m44;

};

 

typedef struct CATransform3D CATransform3D;




 

The example in Listing 2 illustrates how to configure a CATransform3D as a perspective transform.

Listing 2  Modifying the CATransform3D data structure directly

 CATransform3D aTransform = CATransform3DIdentity;

// the value of zDistance affects the sharpness of the transform.

zDistance = 850;

aTransform.m34 = 1.0 / -zDistance;




Modifying a Transform Using Key Paths

Core Animation extends the key-value coding protocol to allow getting and setting of the common values of a layer's CATransform3D matrix through key paths. Table 4 describes the key paths for which a layer’s transform and sublayerTransform properties are key-value coding and observing compliant.

Table 4  CATransform3D key paths

Field Key Path

Description

rotation.x

The rotation, in radians, in the x axis.

rotation.y

The rotation, in radians, in the y axis.

rotation.z

The rotation, in radians, in the z axis.

rotation

The rotation, in radians, in the z axis. This is identical to setting the rotation.z field.

scale.x

Scale factor for the x axis.

scale.y

Scale factor for the y axis.

scale.z

Scale factor for the z axis.

scale

Average of all three scale factors.

translation.x

Translate in the x axis.

translation.y

Translate in the y axis.

translation.z

Translate in the z axis.

translation

Translate in the x and y axis. Value is an NSSize or CGSize.

You can not specify a structure field key path using Objective-C 2.0 properties. This will not work:

myLayer.transform.rotation.x=0;

Instead you must use setValue:forKeyPath: or valueForKeyPath: as shown below:

[myLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"transform.rotation.x"]




 [펌]http://developer.apple.com


 

반응형

Animation Framework 개발하기.

UI Framework에 Animation을 접목시키면 그 파급효과는 무시할 수 없다는 결론은 이미 iOS 나 Andriod를 통해서 입증이 되었다고본다.

그런 의미에서 animation framework을 설계/구현 해보는 경험은 매우 중요하리라 보인다.

목표는 Core Animation 과 같은 rendering task가 분리된 형태의 framework 을 구현하는 것이다.

컨셉 모델 구상




구성요소

Engine
   Renderer
   Object Manager
           Object ( Image, Rectangle, Text...)
           Controller
   Animator
           Animation Object
                       ( Transform, Rotation...)

Client
   Object
   Animation
   Controller

Base
   Data type 

  2011.09.19
- Animator 완성
       : Animation - Transform, Value
       : TimeLine - Bezier, Linear Easy, FadeIn, FadeOut
- Face Tree 구축
       : Face property : Bounds , Fg color,bgColor, opacity , visible
       : RootFace, ImageFace ,BoxFace,TextFace
- Communication
       : Command, FaceCommand
       : CommandQueue, Executor
       : CommandParser
- Property
       : Value , Property ,PropertyT(template),PropertyReceiver
      



반응형

key 값과 value 로 data를 관리하는 형태는 상당히 편리하고 유용한 기법입니다.

최근 iCloud에서 이런 key /value 관리 기법을 사용하여  내가 구입한 책 정보, 현재 읽고있는 책의 북마크 , Contact 정보 등을 
관리하고 보관 update 한다고 스티브 잡스 님이 예기 하여 약간 화제가 되고 있는 기술입니다.

우선 iOS 의 경우에는 Objective-C의 언어 적인 특징으로 key-value 기능 지원이 자연스럽게 구축되어있는 상황이라고 보여집니다.  (NSResponsible, NSObject , NSProxy 정보에 기술되어있습니다.)


key-Value 컨셉을 C++에서 비슷한 성격의 클래스를 만들수 있지 않을까 해서 ,  디자인/ 구현 해보고자 아래와 같이 구상했습니다.

우리가 class를 설계 할때 대부분 class의 기능을 생각하고, 필요한 속성을 찾고 이를 멤버변수로 정하고, 멤버변수에 접근하는 API를 설계해서 추가한다.
그러면 아래와 같은 형태가됩니다.

class TitleBox
{
...
public:
   void SeBounds(int x,int y,int w,int h);
   void GetBounds(int *x,int *y,int *w,int*h);
   void SetBgColor(RGB col);
   void GetBgColor(RGB * col);
   void SetText(string &text);
   string &GetText();
   
protected:
  string m_Text;
  Rectangle m_Bounds;
  RGB m_bgColor;
};

이렇게 설계가 되고 나면, 그다음에 이 class를 사용해서 뭔가를 만들기 시작하는데,
한참 모듈을 만들다 보면 "아 Text Color 도 변경이 되어야 겠네!!" 하게 됩니다.

그래서 Text Color를 변경하는 API를 추가하고, 멤버 변수도 추가하죠.

그리고 한참 작업하다보면, Icon 추가하는 기능도 필요하게 되고, 
BgColor 대신 bg image를 사용하고 싶어질때도 있고, 그때 마다 API를 추가하거나 변경하고,
해당 API를 사용하는 모든 곳을 찾아서 다시 수정해야 합니다.

또... 멤버 변수의 종류가 점점 늘어나면 늘어날 수록 API 개수는 거의 2배정도로 늘어나게 되고, 
이를 관리하는 것도 힘들어지게 되죠.

그래서 개발자들은 이를 획기적으로 개선할 수 있는 방법들을 하나 둘씩 생각하기 시작합니다.

그래서 control의 속성을 나타내는 멤버 변수들을 묶는 컨셉이 나오게 됩니다.
이를 attribute 나 property 라는 이름으로 설명하곤하는데요. property라고 하겠습니다.

그러면서 property의 내용을 속성마다 일일히 멤버 변수를 정의 하는 것이 아니라,
STL의 map 과 같이 key와 value 로 관리하는 방법을 취하게 됩니다.

property.set("bounds.x",10);
property.set("bounds.y",10);
property.set("bounds.w",10);
property.set("bounds.h",10);
property.set("bg.color",RGB(100,210,113));
property.set("bg.image","user/bg_ship.jpg");

property.get("bounds.x",&cx);


이런 형태를 취하게 됩니다.

이로 인해서 class의 확장이나 기능 변경시에 API의 변경 폭이 줄어들게 되어, 유지 보수에 매우 효과적인 결과를 나타내게 됩니다.

이와 더불어 부가적인 효과로 control을 조작할때 더이상 해당 control의 class를 알 필요가 없어지게 되었습니다.
단순한 기능의 경우 property만 parameter로 넘겨받아서 property의 속성값을 확인하면 되기 때문에 모듈간의 dependency가 줄어들게 된 것입니다.

[Button.h]----------------------------
class Button
{
 void SetText();
};
--------------------------------------


[ButtonUI.c]--------------------------

#include "Button.h"

class ButtonUI
{
protected:
   Button * m_pButton;   //<--- 이와 같이 실제로 Button class를 알아야만 조작이 가능해 집니다.
public:
   void ChangeText();
};

ButtonUI::ChangeText()
{
    m_pButton->SetText();
}
--------------------------------------
그런데 만약 Property를 이용하게 된다면,
ButtonUI는 더이상 Button class를 알 필요가 없어지고, Property 만 control로 부터 얻어올 수 있으면 property만 조작하는 것이 가능해 집니다.

이는 class factory 형식을 이용하여, class의 instance를 생성해주는 모듈과 함께 사용된다면,
class간의 의존성을 획기적으로 줄일 수 있게 됩니다.

그리고 data를 접근하는 기법이 통일되어 여러가지 형태로 활용이 가능해 지게 됩니다.


XML이나 script같은 engine을 활용하여 property를 조작하는 부가적인 기능도 만들 수 있게되고,
property만 따로 registry에 저장하여 , 현재 상태를 임시로 저장했다가 다시 실행할때 동일한 형태로 불러오는 것도 가능해집니다.





반응형


스콧 마이어스 

참. 주옥같은 한줄 한줄이 들어있는 책이죠.
GOF 디자인 패턴과 함께 손에 놓을 수가 없네요. 왠만한 소설책보다 재미있다는...ㅋ
2판은 후배가 본다고 해서, 서점에 들려서 3판을 주문해서 다시 보게 되었답니다. ㅎ


[Effective C++]

복사생성자와 대입연산자 처리 - 만약 내가 만들려는 class가 만약 복사가 필요없다면, 원천 차단 하라.!
     - 항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자!
        복사 생성자와 대입 연산자 private으로 선언하기! 

복사 생성자와 대입 연산자 예기가 나오니 몇달전에 겪었던 한 사건이 생각나네요. ㅎ

DLL 모듈을 작성하면서 만든 class가 있었는데, 우연찮게 다른 프로젝트에서 해당 class 와 같이 들어있던 define이 필요해서 include를 한적이 있었습니다. 다른 class들은 다 문제가 없었는데 유독 한 class에서 link error가 발생하더군요.
__declspec(dllexport) 로 선언되어있는 것이 문제긴 했는데, 다른 class들은 다 문제가 없는데 왜?????? 이 class만 문제가 되는가로 고민을 하게 되었습니다. 

그런데 원인은 알겠는데, 그렇다면 똑같이 선언된 다른 class들은 왜 문제가 없었는가? 하는것이었죠.
이걸로 한 2시간 고민하다가 해더파일의 class코드를 다 지우고, 문제가 발생하지 않은 녀석과 문제가 발생한 녀석 2개를 놓고, 한줄 한줄 copy하면서 비교해 봤습니다.

결국 두 클래스간의 차이는 복사연산자와 대입연산자가 금지되어있는가 아닌가 의 차이더군요.
대입연산자 (operator =)를 금지 시켰더니 문제가 해결되더군요.



변수 초기화
C와 C++의 차이.
우선 C는 기본적으로 변수 초기화가 안되죠. C++은 객체이기 때문에 객체를 생성하는 시점에 초기화가 기본적으로 되죠.(constructor 불리니까 말이죠).

C의 경우 물론 다른 정책을 가지고 있습니다. C++ 예기에 주로 관심이 있으니 넘어가도록 하겠습니다.

항목 4: 객체를 사용하기 전에 반드시 그 객체를 초기화 하자.
를 살펴보면 이런 대목이 있습니다.
"C++의 객체 초기화가 중구난방인것은 아니다. 언제 초기화가 보장되며 언제 그렇지 않은지에 대한 규칙이 명확히 준비되어있다. 그런데 복잡하다."
뭐 대충 이런 구문인데,과연 무엇이 복잡한가?
 
정적객체(static object) 중에서 비지역적 정적 객체와  지역 정적 객체가 있는데, 함수내의 static object만 지역 정적 객체이고 나머지는 비 지역적 정적객체입니다.  
비 지역적 정적 객체는 compiler가 생성시점을 결정하기 때문에 생성 순서나 초기화 순서를 개발자가 결정할수 없게 됩니다. 
때문에 비지역적 정적객체를 지역 정적객체로 바꿔서 사용하는 것이 일반적입니다.

CWindowManager * CWindowManager::GetInstance()
{
static CWindowManager windowManager;
return &windowManager;
}

또는
CWindowManager * CWinMgr(void)
{
static CWindowManager windowManager;
return &windowManager;
}

이런식이죠. 말은 어렵지만 코드는 단순합니다. ㅎ
코딩할때는 이렇게 사용하겠죠.

CWindowManager * pWinMgr = CWinMgr();
또는
CWindowManager * pWinMgr = CWindowManager::GetInstance();
 
pWinMgr->GetWindow(x,y);



컴파일러의 종류나 구현에 따라 다르게 동작하는 부분
 - 항목17: new로 생성한 객체를 스마트 포인터로 저장하는 코드는 별도의 한 문장으로 하자.

책에 있는 예제로 가보면,
int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw,int priority);
     :
processWidget(std::tr1::shared_ptr<Widget>(new Widget) , priority());

의 예제 코드를 보면, resource leak이 발생할 가능성이 있답니다.
컴파일러가 processWidget 호출 코드를 만들기 전에 우선 이 함수의 매개변수로 넘겨지는 인자를 확합니다.
이때 첫번째 인자인 std::tr1::shared_ptr<Widget>(new Widget)는 2부분으로 나뉩니다.

- new Widget
- tr1::shared_ptr -> 생성자 호출부분

때문에 processWidget을 호출하기 전에, 컴파일러는 
priority()를 호출하는 부분,
new Widget 을 실행하는 부분.
tr1::shared_ptr 생성자를 호출하는 부분.

위와 같이 3부분으로 나뉜다고 한다면, 컴파일러에 따라, priority() -> new Widget -> tr1::shared_ptr 생성자 호출의 순서가 될 수도 있고, new Widget -> priority() -> tr1::shared_ptr 생성자 호출 이 순서가 될 수도있습니다.

두번째 경우 priority() 에서 exception이 발생한다면, new Widget으로 생성한 포인터는 유실될 가능성이 있습니다.
자원 유실을 막기 위해 shared pointer 를 사용했는데, 예측할 수 없는 위치에서 자원이 유실된 케이스겠죠.

이럴 바에야 
std::tr1::shared_ptr<Widget>pw(new Widget);
processWidget(pw,priority());
를 따로 써서 고민꺼리를 미리 예방하는게 좋겠다.!!! 는 것...


강력한 보장: 함수가 호출되고 내부에서 error 처리 루틴에 의해 fail을 return할때는 함수가 호출된적이 없었던 것 처럼 깔끔하게 프로그램 상태가 돌아가게 한다.는... 
- 항목 29:예외 안정성이 확보되는 그날 위해 싸우고 또 싸우자!

Hiding: ????
-항목 33:상속된 이름을 숨기는 일은 피하자
음.. 아마 대부분의 경우 의도적으로 상속된 멤버의 이름을 숨기는 일은 별로 없을것이다.
우연찮게, 또는 실수에 의해서 HIDING되는 경우가 많다. 
- 이런 경우 정말 c++에 대해서 잘 알지 못하면, 문제의 원인을 알아내기 힘들다. 또 잘알고 있더라도 찾아내기 힘들다.
  다행히도 이럴때 compiler가 warning을 내주긴 한다.
다음 예제를 보자!(Effective C++에 나온 예를 노가다 타이핑 했습니다. ㅡㅡ;;)

class Base{
private:
   int x;
public:
  virtual void mf1()=0;
  virtual void mf1(int);
  virtual void mf2();
  virtual void mf3();
  virtual void mf3(double);
  ...
};

class Derived: public Base
{
public:
  virtual void mf1();
  void mf3();
  void mf4();
};

void test_main(void)
{
Derived d;
int x;
...
d.mf1(); //좋습니다. Derived::mf1을 호출합니다.
d.mf1(x);//에러. Derived::mf1이 Base::mf1을 가립니다.
d.mf2();//좋습니다. Derived::mf2을 호출합니다.
d.mf3();//좋습니다. Derived::mf3을 호출합니다.
d.mf3(x);//에러. Derived::mf3이 Base::mf3을 가립니다.
}

어 ! 왜 에러지? 이런 의문을 품게 될것입니다. "상속받은 서브클레스가 슈퍼클레스의 멤버를 호출하는데 왜 에러지?" 라고 말이죠.!!
하이딩에 대해서 모르고 있기 때문입니다.

C++ 의 네이밍 규칙중에 하나인, 기본 클래스로부터 오버라이드 버전을 상속시키는 경우는 막겠다.
즉, 슈퍼클레스에 정의된 이름과 동일한 이름을 서브클레스에서 정의해서 사용하게 되면, 서브클래스 내에서는 슈퍼클레스의 이름을 모두 가리겠다(hiding)는 의미입니다.
"warning: Deriver::mf1() hides virtual Base::mf1()" 이런 워닝을 보이면서 말이죠.


[More Effective C++]

예외(Exception)

"예외 처리는 프로그램을 여러가지 면에서 흔들어 놓습니다." 그 증세는 심각하고 급진적이며 불편하기까지 합니다.
초기화 되지 않은 포인터를 사용하는 것이 위험해지고, 리소스 누수가 발생할 가능성의 가짓수도 늘어납니다.
우리가 원하는 대로 작동하는 생성자와 소멸자를 만들기가 보다 더 힘들어집니다.
예외처리 기능이 들어간 실행 파일과 라이브러리는 덩치도 늘어나고 속도도 느려집니다.

또 어떻게 해야 제대로 사용하는지 모릅니다.(예외가 발생했을때 어떻게 해야 적절하고 안정적으로 동작하게 하는 벙법에 대해서 의견일치가 아직도 이뤄지지 않았다는 것입니다.)

여기 내용을 찾아보시기 바랍니다. - EXCEPTIONHANDLING: 
A FALSE SENSE OF SECURITY 
byTom Cargill


setjump 와 longjump 는 exception 처리하는 루틴과 비슷하다. 차이라면, 스택을 거슬러 올라가면서 스택 내의 c++ 객체의 소멸자를 호출하지 않는 다는 것이다.


항목 9: 리소스 누수를 피하는 방법의 정공은 소멸자이다.

void processAdoptions(istream & dataSource)
{
while(dataSource)
{
ALA* pa = readALA(dataSource);
try{
pa->processAdoption(); // 예외를 던질 녀석
}
catch(...)
{
delete pa;
throw;
}
delete pa;
}
}

위와 같이 pa->processAdoption()에서 예외를 던질것을 예상하고 코드는 복잡하게 처리되기 마련이다.
이를 스마트 포인터를 써서 구현하게 되면 훨씬 간결한 코드가 나오게 된다.

void processAdoptions(istream &dataSource)
{
while(dataSource)
{
auto_ptr<ALA> pa( readALA(dataSource) );
pa->processAdoption(); // 예외를 던질 녀석
}
}

위 처럼 pa->processAdoption()가 예외를 던지더라도 while 구문을 빠져 나갈때 auto_ptr<ALA>의 소멸자가 불리면서 내부에서 ALA의 소멸자를 호출하기 때문에, 훨씬 간결해지고, 리소스 관리가 편해지게 됩니다.


항목 10: 생성자에서는 리소스 누수가 일어나지 않게 하자

C++은 생성과정이 완료된 객체에 대해서만 안전하게 소멸 시킵니다. 만약 생성자 내부에서 exception이 발생하게 되면, 해당 객체의 소멸자는 호출되지 않습니다.


항목 11: 소멸자에서는 예외가 탈출하지 못하게 하자.
예외처리가 진행되고 있는 동안 다른 예외 때문에 소멸자를 떠나게 되면, C++은 terminate란 함수를 호출하게 되어있습니다.
이 함수는 프로그램의 실행을 끝장내기 때문에, 것도 아주 칼같이 끝내 버리기 때문에,지역 객체조차도 소멸되지 않습니다.

Session::~Session()
{
try{
logDestruction(this);  // 예외를 던지는 녀석
}
catch(...){ }    //expction으로 소멸자를 빠져 나가는 것을 잡고있는 녀석
}

위의 try catch구문만으로도 아주 훌륭한 소멸자 예외처리가 되는 것입니다.

항목 15: 예외처리에 드는 비용에 대해 정확히 파악하자

통상적인 함수 복귀(return)과 비교할때 , 예외 발생(throw)에 의한 함수 복귀 속도는 10의 세 제곱배(1000배) 만큼 느리다고 합니다.

예외 비용을 최소화 하려면, 가능하다면 예외 기능을 지원하지 않도록 컴파일하십시오.
try 블록과 예외 지정은 꼭 필요한 부분에만 사용합니다. 예외를 발생시키는 일도 진짜 예외적인 상황이라고 판단될 때에만 해야 합니다.

80-20 법칙 : 예외 자체는 사실 프로그램의 동작상 20에 해당합니다. 프로그램의 성능에 영향을 크게 미치는 것이 아닙니다.
단지 예외 발생이 자주 일어난다면, 그때는 예외를 사용할 것인지 심각하게 고려해봐야 합니다.




오 남용.



반응형

html 5를 공부하기 좋은 sample 자료네요..
이것 저것 해볼것도 많고 ㅎ


+ Recent posts